将ArrayList元素克隆到相同的ArrayList

时间:2012-11-17 21:01:39

标签: java arraylist clone

我有一个包含对象的ArrayList。 (这个对象是clases,每个对象包含非常大量的信息,这些对象恰好代表大型发电机,因此不能一个一个地复制属性。)

示例:

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

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

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

但不知何故,这样做,ob5不是ob ob1副本,它是ob1,所以如果我改变ob5,ob1也会改变。

这是ArrayLists固有的东西吗? 如果我使用列表,有什么区别吗?

9 个答案:

答案 0 :(得分:2)

ArrayList保存引用yes。但你可以克隆它(注意!但它将是浅拷贝 - 它也不会克隆内部对象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

答案 1 :(得分:1)

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

浅拷贝:如果在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;
  }
}

答案 2 :(得分:0)

在Java的任何地方都是如此。除非您明确这样做,否则 Nothing 将被复制。 (事实上​​,有些物品是故意无法复制的。)

答案 3 :(得分:0)

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

一旦你有了,你可以做到

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

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

答案 4 :(得分:0)

这与ArrayList无关,这是一个java功能。未创建新对象,仅传递引用。因此,ArrayList存储两个引用。你必须使用对象的.clone()方法。

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

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

答案 5 :(得分:0)

不,这是因为在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/

答案 6 :(得分:0)

该列表仅包含指向对象的指针..

如果你将ob1移动到ob5会发生什么事情,你告诉列表将指针放到ob5指针所在的ob1,因此丢失指向ob5的指针并将指针复制到ob1 ... < / p>

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

答案 7 :(得分:0)

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

int x = 2;
int y = x;

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

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

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

答案 8 :(得分:0)

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