【问题标题】:Clonning ArrayList element to the same ArrayList将 ArrayList 元素克隆到相同的 ArrayList
【发布时间】:2012-11-06 05:59:27
【问题描述】:

我有一个包含对象的ArrayList。 (这个对象是类,每个对象都包含大量的信息,正是这些对象代表了大型发电机,所以不能一个一个地复制属性。

示例:

ArrayList arr = {ob1, ob2, ob3, ob4, ob5}

所以我尝试做的是将对象(ob1)克隆到位置 5。

arr.set(4, arr.get(0));

但是不知何故,这样做,ob5 不是复制 ob1,而是 ob1,所以如果我更改 ob5,ob1 也会更改。

这是 ArrayLists 固有的吗? 如果我改用 List 有什么不同吗?

【问题讨论】:

    标签: java arraylist clone


    【解决方案1】:

    ArrayList 保存引用是的。但是你可以克隆它(注意!但这将是浅拷贝 - 它不会克隆以及内部对象https://stackoverflow.com/a/13434779/1111527

    private class JustToCheck implements Cloneable {
    
        @Override
        public Object clone() throws CloneNotSupportedException {
            return super.clone();
        }
    }
    

    然后像这样使用

    JustToCheck ob1 = new JustToCheck();
    JustToCheck ob2 = ob1;
    
    List<JustToCheck> arr = new ArrayList<JustToCheck>();
    arr.add(ob1);
    arr.add(ob2);
    
    System.out.println(arr.get(0).toString() + ": " + arr.get(1).toString());
    
    try {
        arr.set(1, (JustToCheck) ob1.clone());
    } catch (CloneNotSupportedException e) {
        e.printStackTrace();
    }
    
    System.out.println(arr.get(0).toString() + ": " + arr.get(1).toString());
    

    输出是

    example$JustToCheck@1c39a2d: example$JustToCheck@1c39a2d
    example$JustToCheck@1c39a2d: example$JustToCheck@bf2d5e
    


    PS - 我已在答案https://stackoverflow.com/a/13434813/1111527

    中检查了该问题

    有一些不可变的类

    Java6

    String a = new String("a");
    String b = a;
    b += "b"; 
    System.out.println("a = " + a); // a = a
    System.out.println("b = " + b); // b = ab
    

    【讨论】:

      【解决方案2】:

      这是因为您正在执行卷影复制而不是深层复制。

      浅拷贝:如果在Obj-1 上执行浅拷贝,则它会被复制,但其包含的对象不会。包含的对象Obj-1Obj-2 受到克隆的Obj-2 更改的影响。当类实现 java.lang.Cloneable 接口时,Java 默认支持对象的浅层克隆。

      深拷贝:如果如图所示对obj-1 执行深拷贝,则不仅obj-1 已被复制其中包含的对象也已被复制。序列化可用于实现深度克隆。通过序列化进行的深度克隆开发起来更快,更容易维护,但会带来性能开销。 source

      深拷贝的一个例子:

      class Student implements Cloneable {
        //Contained object
        private Subject subj;
        private String name;
      
        public Subject getSubj() {..}
        public String getName() {..}
      
        public Object clone() {
          //Deep copy
          Student s = new Student(name, subj.getName());
          return s;
        }
      }
      

      【讨论】:

        【解决方案3】:

        这在 Java 中的任何地方都是正确的。 没有任何东西会被复制,除非你明确地这样做。 (确实,有些对象是故意无法复制的。)

        【讨论】:

          【解决方案4】:

          您需要复制您的ElectricGenerator。最常见的选项是引入复制构造函数或实现克隆方法。然而,这两种解决方案都需要复制所有这些属性。

          一旦你有了它,你就可以做到

          //copy constructor
          arr.add( new ElectricGenerator( arr.get( 0 ) ) );
          //clone
          arr.add( arr.get( 0 ).clone() );
          

          另一种方法是序列化/反序列化对象

          【讨论】:

            【解决方案5】:

            这不符合 ArrayList,这是一个 java 特性。没有创建新对象,只传递了一个引用。 ArrayList 因此存储了两个引用。您必须使用对象的 .clone() 方法。

            arr.set(4, arr.get(0).clone());
            

            这将创建对象的新副本,即使此副本很浅。如果需要,您必须重写 clone 方法以使其成为深层副本。

            【讨论】:

              【解决方案6】:

              列表只包含指向对象的指针..

              如果您将 ob1 移动到 ob5 会发生什么情况,您告诉列表将指向 ob1 的指针放在 ob5 的指针所在的位置,因此丢失指向 ob5 的指针并复制指向 ob1 的指针...

              您需要创建另一个包含重复值的对象,然后将此对象分配给位置 4

              【讨论】:

                【解决方案7】:

                对象变量不同于原始数据类型。

                int x = 2;
                int y = x;
                

                x 和 y 指代不同的内存位置。

                MyClass x = new MyClass();
                MyClass y = x;
                

                x 和 y 引用相同的内存位置,但该位置有两个引用。对其中一个所做的任何更改都会改变另一个。解决此问题的方法是实现Cloneable 并使用.clone() 方法。

                【讨论】:

                  【解决方案8】:

                  不,这是因为在 Java 中你创建了对对象的引用,所以即使你不使用 ArrayList 并执行以下操作:

                  String a = new String("a");
                  String b = a;
                  
                  b += "b";
                  

                  a 和 b 都等于 "ab"。

                  (例外是 int 等基本类型(但不是 Integer 的实例有不同的东西)。

                  所以你的问题的答案在这里: How to copy an object by value, not by reference 和这里 : http://www.itcsolutions.eu/2010/12/29/tutorial-java-6-4-2-how-to-copy-values-of-an-array-into-another-array/

                  【讨论】:

                    【解决方案9】:

                    shallow copying 创建同一个类的新实例并将所有字段复制到新实例并返回它。 Object 类提供克隆方法,支持浅拷贝。

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2010-10-17
                      相关资源
                      最近更新 更多