List<Object>
。每次列表可能由来自不同类型的元素组成。这是一种通用的方法,我不知道它们的类类型将是什么。在允许用户更改值之前,我想保存该列表的副本。但是由于复制是通过引用进行的,因此两个列表(原始列表和副本)都会被更改...
如何按值复制我的列表?
List<Object>
。每次列表可能由来自不同类型的元素组成。这是一种通用的方法,我不知道它们的类类型将是什么。你的问题不够清晰。
如果你想要一个浅复制(即列表的副本将包含对原始列表中对象的引用),那么clone
方法或者在List
实现类上使用复制构造函数都可以完成任务。
如果你想要一个深复制(即列表的副本包含原始对象的副本),那么最好的方法是创建一个新列表,并使用原始列表元素的克隆来填充它。但是,有一个问题。默认情况下不提供clone
方法。许多常见的实用程序类都是可克隆的,但自定义类通常不是...除非你已经实现了它。如果你的列表包含任何不可克隆的对象,你将在运行时得到异常。
还有其他深度复制替代方案,但与克隆一样,它们不能适用于所有类。而且,如果你的解决方案必须是通用的,这真的是问题的关键。
List
,然后将原始列表的每个元素的克隆添加到其中。List<Object> copy = new ArrayList<Object>(inputList.size());
for (Object item : inputList) {
copy.add(item.clone());
}
Cloneable
,否则它们将不能正确地被复制。Collections.copy(b,a);
(3)在理想情况下,创建一个新列表,并用明确创建的“副本”填充它。如果编码不太麻烦,这是理想的解决方案,因为你“知道实际发生了什么”:在对象意外重新引用而不是重新创建的情况下,不会有隐藏的意外惊喜,例如clone()方法没有按预期工作。
由于您拥有一个简单的容器对象(数组列表),其结构可以轻松重新创建,因此(2)可能过度。对于重新创建更复杂的结构,它可能很方便。
关于(1),您应该特别怀疑从第三方库中克隆对象,其中对象并非专门设计为考虑clone()。问题在于人们很容易从JDK(可克隆)类或者一个标记的clone()方法进行子类化,而不会详细考虑它——根据我的经验,clone()具有许多开发人员不知道的细微差别(例如构造函数不会在新对象上调用),这可能导致意想不到的问题。因此,如果您无法看到可靠的源代码以确保clone()是安全的,我建议避免使用它。
遍历传递的列表并复制其内容以创建一个新列表,然后可以使用该新列表而不更改原始列表。
private List<Object> clone;
public Foo(List<Object> original)
{
this.clone = new ArrayList<Object>(list.size());
for(Object item: original)
{
clone.add(item.clone());
}
}