【问题标题】:ArrayList.add(idx,element) corrupt other element of arrayArrayList.add(idx,element) 损坏数组的其他元素
【发布时间】:2015-07-02 09:38:00
【问题描述】:

我正在运行一个程序:

  1. 创建一个ArrayList
  2. 在这个数组的顶部添加一些元素
  3. 创建一个“基础”元素,该元素将被减少
  4. 然后使用 for 循环减少基本元素并将其添加到数组顶部(索引 0)
  5. 没想到我得到的输出太可怕了

请不要为一些意大利语单词感到难过:

  • “ora”表示小时,所以

    Ora hour = new Ora(6,34) //--> 6:34
    
  • “decrementaMinuti”从小时开始减少分钟数

这是完整的代码:

public static void main(String[] args) {

    ArrayList<Ora> hours = new ArrayList<>();

    hours.add(0, new Ora(01,00));
    hours.add(0, new Ora(00,00));

    Ora base = hours.get(0);
    System.out.println("Base: " + base + "\n");        

    for (int i = 0; i < 4; i++) {

        System.out.println("First: " + base);
        // decreasing 60 minutes from hour
        base.decrementaMinuti(60);

        System.out.println("After: " + base);
        hours.add(0, base);

        System.out.println("In Array: " + hours.get(0));

        System.out.println("[hours]");
        for (int j = 0; j < hours.size(); j++) {
            System.out.println("[" + hours.get(j) + "]");
        }

        System.out.println("- - - - - - - -\n");
    }

}

这是我得到的输出:

Base: 11:00

First: 11:00
After: 10:00
In Array: 10:00
[hours]
[10:00]
[10:00]
[12:00]
- - - - - - - -

First: 10:00
After: 09:00
In Array: 09:00
[hours]
[09:00]
[09:00]
[09:00]
[12:00]
- - - - - - - -

First: 09:00
After: 08:00
In Array: 08:00
[hours]
[08:00]
[08:00]
[08:00]
[08:00]
[12:00]
- - - - - - - -

First: 08:00
After: 07:00
In Array: 07:00
[hours]
[07:00]
[07:00]
[07:00]
[07:00]
[07:00]
[12:00]
- - - - - - - -

在最后一个输出块中,有一个小时 7:00 5 次,而我从来没有两次添加相同的小时。

我在问:为什么(如您所见)在这个数组的顶部添加一个元素会导致后面的元素也被破坏?

我的java版本:

java version "1.7.0_79"
Java(TM) SE Runtime Environment (build 1.7.0_79-b15)
Java HotSpot(TM) 64-Bit Server VM (build 24.79-b02, mixed mode)

非常感谢您提供的任何帮助。

【问题讨论】:

    标签: java arrays arraylist corruption


    【解决方案1】:

    您正在向列表中多次添加同一个实例:

    Ora base = hours.get(0); // this is the instance added multiple times
    System.out.println("Base: " + base + "\n");        
    
    for (int i = 0; i < 4; i++) {
    
        System.out.println("First: " + base);
        // decreasing 60 minutes from hour
        base.decrementaMinuti(60);
    
        System.out.println("After: " + base);
        hours.add(0, base); // here you add the same instance multiple times
    

    在将其添加到列表之前,您必须创建一个新的 Ora 实例:

    Ora base = hours.get(0);
    System.out.println("Base: " + base + "\n");        
    
    for (int i = 0; i < 4; i++) {
    
        System.out.println("First: " + base);
        Ora newOra = new Ora (...); // consider having a copy constructor that
                                    // would accept base and copy its data
        // add code to update newOra to contain the same data as base
    
        // decreasing 60 minutes from hour
        newOra.decrementaMinuti(60);
    
        System.out.println("After: " + newOra);
        hours.add(0, newOra); // add the new instance
    

    【讨论】:

      【解决方案2】:

      您正在添加相同的对象Ora base = hours.get(0),而您只是更改了对象的内容。然而是相同的参考。 ArrayList 允许您多次添加同一个对象引用,但 ArrayList 中的条目实际上是引用同一个对象,并且与数据相同的内存区域。这就是为什么所有人都打印相同的结果。

      【讨论】:

      • 接受以获得更好的解释。非常感谢!
      【解决方案3】:

      实际上是因为当你这样做时:“Ora base = hours.get(0);” base 不是变量的副本。事实上,Java 总是指针。

      hours.add(0, base);将导致添加相同的一、二或三倍。

      【讨论】:

      • 误导性答案,java 严格按值传递,而不是按引用(或指针)传递。但是,传递的值是堆栈上的值,对于对象来说,它是对对象堆中内存地址的引用。
      猜你喜欢
      • 1970-01-01
      • 2018-08-13
      • 1970-01-01
      • 1970-01-01
      • 2017-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-08
      相关资源
      最近更新 更多