1

我在 Java 中对对象的引用有问题。这是情况。

假设我有一个名为 MyObject 的对象类。

class MyObject {
      Long id;
      String item;
      Integer number;
      BigDecimal bigNumber;
      //and Some getter and setter methods 
}

假设我有哈希图:

HashMap<Long, MyObject> myHash = new HashMap<Long, MyObject>();

我用 MyObject 的一些对象填充这个 hashmap。

然后,当我尝试将此 hashmap 的所有元素复制到 arrayList(使用 addAll 方法)时,hashmap 中包含的所有对象都将复制到具有相同引用的arraylist。出于这个原因,当我尝试更改 hashmap 中的 MyObject 对象时,它也在 arrayList 中更改。我不想要那个。我该如何防止呢?

我希望我清楚地告诉问题。

提前致谢。

4

4 回答 4

1

目前您只是在复制参考资料。这样做是因为复制对象非常昂贵。

在您的情况下,您想要复制对象,因此您需要在将它们添加到列表时复制每个对象。就像是

for(MyObject mo: myHash.values())
    list.add(mo.copy());

您可以通过多种方式实现复制,包括使用 clone();

于 2013-05-11T17:41:31.870 回答
1

MyObject我将通过实现Cloneable接口使类可克隆,请参阅Cloneable Javadoc

Java 复制引用而不是对象。学习和理解这一点很重要。在您的情况下,您想要复制对象,因此您必须实现一个方法,该方法通过地图,复制您的对象,并将对这些副本的引用放入数组中。

如果您需要更多关于 Java 克隆的信息,这个 Wikipedia 页面是一个很好的来源。

解决方案可能如下所示:

  • MyObject通过实现Cloneable接口使类可克隆。Object具有clone()复制所有字段的方法的默认实现。在您的情况下,您有LongStringIntegerBigDecimal字段。它们都是不可变的,所以它们不需要自己克隆,这就是为什么你不需要在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());
    }
    
于 2013-05-11T17:51:48.233 回答
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());
}
于 2013-05-11T17:42:07.123 回答
0

在将 MyObject 添加到 arraylist 之前,您需要克隆/复制它们。当您使用 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;
} 
于 2013-05-11T17:48:03.023 回答