2012-11-17 88 views
2

我有一个ArrayList包含对象。 (这些对象是分类,每个对象都包含大量的信息,这些对象恰恰代表了大型发电机,因此不能一个一个地复制这些属性)。Clonning ArrayList元素到相同的ArrayList

例如:

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

所以我尝试做的是克隆的对象(OB1)的位置5

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

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

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

回答

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; 
    } 
} 
0

这将是真正的在Java中的任何地方。 没有将得到复制,除非你明确这样做。 (的确,有些对象故意不可复制。)

0

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

一旦你有,你可以做

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

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

0

这不是附着于ArrayList中,这是一个Java功能。新对象不会创建,只会传递一个引用。 ArrayList因此存储两个引用。你必须使用你的对象的.clone()方法。

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

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

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/

0

名单只包含指向一个对象..

如果将OB1到OB5会发生什么它告诉列表将指针指向ob1的指针所在的ob1,因此丢失指向ob5的指针并复制ob1的指针...

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

0

对象变量与基本数据类型不同。

int x = 2; 
int y = x; 

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

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

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

0

shallow copying创建相同类的新实例并将所有字段复制到新实例并将其返回。对象类提供了一种克隆方法,并为浅拷贝提供支持。

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()); 

输出被

[email protected]: [email protected] 
[email protected]: [email protected] 


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