我正在使用一个用于保存和调用屏幕状态的系统,这是我第一次弄这种东西,所以我不确定如何解决此问题的最佳方法是什么,但是我目前存储了所有“ PreviewMonitor”数组列表中的对象(大约40个左右)。问题是,当我创建要存储的名为“ allPreviewMonitors”的ArrayList的副本时,最终得到的ArrayList的元素随着原始元素的更新而不断变化。实际上,好像我正在使用原始ArrayList一样,当我创建allPreviewMonitors的副本时,它应该是一个完全不同的ArrayList,其中包含元素及其状态的“冻结”版本。为什么会发生这种现象?如果需要的话,我可以显示代码,但是我不确定这里是否需要它。
您仅将对象引用复制到ArrayList中。您需要复制对象本身。
在Java中,所有对象变量实际上都是引用变量。所以代码:
Myclass myObject = new Myclass(); Myclass otherObject = myObject;
创建MyClass对象,并将对该Myclass对象的引用存储在引用变量中myObject。然后,它创建一个新的参考变量otherObject,并将参考数据(例如,内存地址)从复制myObject到otherObject。现在,它们引用内存中的同一对象。此时,线
myObject
otherObject
myObject.myMethod();
具有与以下相同的结果
otherObject.myMethod();
您在ArrayList中得到的是对相同对象的不同引用。您想要的是以下之一:
Myclass otherObject = myObject.clone(); // use the clone function // OR Myclass otherObject = new Myclass(myObject); // use a copy constructor
如果使用clone()或副本构造函数将对象放入ArrayList ,则ArrayList将包含对相同副本的引用,而不是对相同副本的引用。
clone()
正如其他人指出的那样,仅复制引用的副本称为“浅副本”,而复制所引用的对象的副本称为“深副本”。
编辑:为了使此方法有效,您的解决方案不仅要在 您的 类上实现,而且还必须在您类中包含的所有类上实现。例如,考虑MyClass哪个具有类型的字段OtherClass:
MyClass
OtherClass
class MyClass { private String foo; private OtherClass bar; private int x; MyClass(String f, OtherClass b, int x) { foo = f; bar = b; this.x = x; } MyClass(MyClass o) { //make sure to call the copy constructor of OtherClass this(new String(o.foo), new OtherClass(o.bar), o.x); } // getters and setters }
请注意,这OtherClass还需要一个副本构造函数!而且,如果OtherClass引用其他类,那么它们也需要复制构造函数。没有办法解决。
最后,您的列表副本将如下所示:
List<MyClass> myNewList = new ArrayList<>(myExistingList.size()); for ( MyClass item : myExistingList) { // use the copy constructor of MyClass, which uses the copy constructor of OtherClass, etc, etc. myNewList.add(new MyClass(item)) }