在单例对象中克隆某些东西

Cloning something inside a singleton object

也许我只是停电了,但我找不到可行的方法来解决我的问题。

我有一个 Class A 的单例对象,其中包含一个 ArrayList<Item>。在 Class C 中,我需要 ArrayList<Item> 的特定 Item(克隆它)。虽然 ArrayList<Item> 应该保持不变,但我需要对 Class C 中的 Item 进行一些修改。我尝试像这样在 Class Item 中实现 Cloneable:

public class Item implements Cloneable {

  private ArrayList<String> mSize = new ArrayList<>();

  protected Object clone() throws CloneNotSupportedException {
    return super.clone();
  }

  public void modifySomething() {
  mSize.clear();
  }

}

之后我想得到 Item 这样的:

class C {

 void foo() {

  Item item = null;

  try {
   item = (Item) A.getInstance().getItems().get(0).clone();
   item.modifySomething();
  } catch (CloneNotSupportedException e) {
   e.printStackTrace();
  }

 }
}

问题是 Item item 在单例对象中也被修改了。

问: 我是不是用错了方法?我怎样才能得到想要的行为?

实际情况是,克隆不是 "deep" 克隆,您仍然引用相同的内容:

private ArrayList<String> mSize = new ArrayList<>();

在你体内 克隆对象。如果它是一个没有 Collection 属性的克隆对象,它就可以正常工作。

Apache Commons Lang 有 SerializationUtils#clone,它在对象图中的所有 类 实现 Serializable 接口时执行深度复制。

item = (Item) SerializationUtils.clone(A.getInstance().getItems().get(0));

这里:

protected Object clone() throws CloneNotSupportedException {
  return super.clone();
}

那基本上就是一个"no op"。它 而不是 神奇地将列表内容复制到新列表中。仅作记录:对于 any 方法,override 确实没有意义,只能调用 super 方法实现。那么你也可以:只是不要重写那个方法。

因此,要么使用不同的机制,要么真的覆盖该方法,使用自定义内容创建新列表。否则,您的克隆和原始 Item 对象在 相同 列表实例上运行。