28

可能重复:
Java:如何克隆 ArrayList 还克隆它的项目?

我有一个示例程序,如下所示:

ArrayList<Invoice> orginalInvoice = new ArrayList<Invoice>();

//add some items into it here

ArrayList<Invoice> copiedInvoice = new ArrayList<Invoice>();

copiedInvoice.addAll(orginalInvoice);


我以为我可以修改里面的项目copiedInvoice,它不会影响里面的这些项目originalInoice。但是我错了。

如何制作一个单独的副本/克隆ArrayList

谢谢

4

4 回答 4

41

是的,这是正确的 - 您需要实现clone()(或其他适合复制对象的机制,clone()许多程序员认为这是“破坏”的)。您的clone()方法应该对对象中的所有可变字段执行深层复制。这样,对克隆对象的修改不会影响原始对象。

在您的示例代码中,您正在创建第二个并使用对相同 objectsArrayList的引用填充它,这就是为什么从两个s 都可以看到对 object 的更改的原因。使用克隆方法,您的代码将如下所示:List

List<Foo> originalList = ...;

// Create new List with same capacity as original (for efficiency).
List<Foo> copy = new ArrayList<Foo>(originalList.size());

for (Foo foo: originalList) {
  copy.add((Foo)foo.clone());
}

编辑:为了澄清,上面的代码正在执行原始对象的深层副本List其中 newList包含对原始对象副本的引用。ArrayList.clone()这与执行 ashallow copy的调用形成对比List。在这种情况下,浅拷贝会创建一个新List实例,但包含对原始对象的引用。

于 2009-08-25T19:00:59.770 回答
22

如果要将可变对象存储到 ArrayList 中,则在复制 ArrayList 时需要复制每个对象。否则,新的 ArrayList 仍将保留原始引用。

但是,如果您要存储不可变对象,则可以使用:

ArrayList copiedInvoice = new ArrayList(originalInvoice);

于 2009-08-25T19:04:06.067 回答
3

我以为我可以修改copyedInvoice 中的项目,它不会影响originalInoice 中的这些项目。

发生这种情况是因为被复制的是引用变量而不是它自身的对象。

因此,您最终会得到两个指向同一个对象的“引用”。

如果您需要复制整个对象,则可能需要克隆它。

但是,如果您不克隆对象的内部属性(如果它们碰巧是其他对象),您可能会遇到问题。

例如下面的类定义不会给你任何问题。

  public class Something {
       private int x;
       private int y;
       private String stringObject;
   }

如果您创建它的副本,您将复制其属性的当前值,仅此而已。

但是如果你的类里面确实有另一个对象,你也可以考虑克隆它。

 class OtherSomething {
        Something something;
       private int x;
 }

如果您执行以下操作:

 Something shared = new Something();

 OtherSomething one = new OtherSomething();

 OtherSomething two = new OtherSomething();

 one.something = shared;
 two.something = shared;

在这种情况下,一个和两个对相同的共享“某物”具有相同的引用变量,并且更改其中一个的值会影响另一个。

这就是为什么使用不可变对象更简单/更好/更容易的原因。

如果您需要更改不可变对象的值,您只需创建一个具有正确值的新对象。

于 2009-08-25T19:16:20.860 回答
-1

看看 ByteArrayOutputStream 和 ByteArrayInputStream。如果您的所有类都实现了 Serializable,那么您可以使用上述类进行复制。

于 2009-08-25T19:19:35.487 回答