我遇到了Java中对象引用的问题。这是情况。
假设我有一个名为MyObject的对象类。
class MyObject {
Long id;
String item;
Integer number;
BigDecimal bigNumber;
//and Some getter and setter methods
}
我们也说我有hashmap:
HashMap<Long, MyObject> myHash = new HashMap<Long, MyObject>();
我用MyObject的一些对象填充这个hashmap。
然后,当我尝试将此hashmap的所有元素复制到arrayList(使用addAll方法)时,hashmap中包含的所有对象都将复制到具有相同引用的arraylist。出于这个原因,当我尝试在hashmap中更改MyObject对象时,它也会在arrayList中更改。我不希望这样。我该如何预防?
我希望我清楚地说出问题所在。
提前致谢。
答案 0 :(得分:1)
目前您只是复制引用。这样做是因为复制对象非常昂贵。
在您的情况下,您想要复制对象,因此在将它们添加到列表时需要复制每个对象。像
这样的东西for(MyObject mo: myHash.values())
list.add(mo.copy());
您可以通过多种方式实现复制,包括使用clone();
答案 1 :(得分:1)
我可以通过实施MyObject
界面使类Cloneable
克隆,请参阅Cloneable Javadoc。
Java复制引用而不是对象。学习和理解这一点很重要。在您的情况下,您希望复制对象,因此您必须实现一个遍历地图的方法,复制对象,并将对这些副本的引用放入数组中。
如果您需要有关Java中克隆的更多信息,this Wikipedia page是一个很好的来源。
解决方案可能如下所示:
通过实现MyObject
接口使类Cloneable
可克隆。 Object
具有方法clone()
的默认实现,它复制所有字段。在您的情况下,您有Long
,String
,Integer
和BigDecimal
字段。所有这些都是不可变的,所以它们不需要自己克隆,这就是为什么你不需要在你班级的clone()
方法中做任何事情。您仍需要覆盖Object.clone()
才能将其公开。如果您的某个字段引用了另一个需要克隆的对象,则需要将代码添加到clone()
。
class MyObject implements Cloneable {
Long id;
String item;
Integer number;
BigDecimal bigNumber;
//and Some getter and setter methods
@Override
public MyObject clone() throws CloneNotSupportedException {
return (MyObject)super.clone();
}
}
编写一种方法,将地图中的对象复制到数组中:
public ArrayList<MyObject> getArray() {
ArrayList<MyObject> list = new ArrayList<MyObject>(myHash.size());
for(MyObject object : myHash)
list.add(object.clone());
}
答案 2 :(得分:0)
您应创建数据副本,然后将副本与列表一起使用:
class MyObject {
..
public MyObject dupe() {
return new MyObject(id, item, number, bigNumber, ..);
}
}
void createList() {
ArrayList<MyObject> list = new ArrayList<MyObject>();
for (Map.Entry<Long, MyObject> e : map.entries())
list.add(e.getValue().dupe());
}
答案 3 :(得分:0)
在将它们添加到arraylist之前,您需要克隆/复制MyObject。使用addAll时,只将对象引用从源集合复制到目标集合,而对象本身则不是。
ArrayList copyTo = new ArrayList()
for( MyObject current : myHash.values() )
{
copyTo.add(copy(current));
}
MyObject copy(MyObject o)
{
MyObject copyObj = new MyObject();
// set attributes here from 'o' to 'copyObj'
return copyObj;
}