我有一个包含对象的ArrayList
。 (这个对象是clases,每个对象包含非常大量的信息,这些对象恰好代表大型发电机,因此不能一个一个地复制属性。)
示例:
ArrayList arr = {ob1, ob2, ob3, ob4, ob5}
所以我尝试将对象(ob1)克隆到位置5。
arr.set(4, arr.get(0));
但不知何故,这样做,ob5不是ob ob1副本,它是ob1,所以如果我改变ob5,ob1也会改变。
这是ArrayLists固有的东西吗? 如果我使用列表,有什么区别吗?
答案 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-1
和Obj-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类提供了一个克隆方法,并为浅层复制提供支持。