是否存在一个Java类,该类实现List接口并在将元素添加到列表时克隆这些元素?这样做的目的是保留将此列表封装为对象。
当然,写一个我自己很容易,例如,获取ArrayList并将其包装在另一个类中,然后在实现add和get方法时调用clone方法。但是,我想问一下Java是否已经提供了这样的类,并可能节省一些繁琐的编码。
答案 0 :(得分:4)
我怀疑一个人存在,原因有两个:
Object.clone()
仅适用于实现@Cloneable
的类型;并且当它起作用时,它只会进行浅表复制(例如,如果对象具有List
字段,它将克隆对列表对象的引用,但不克隆其元素);达到自己的目的。 Info about Java cloning problems。因此,为了使克隆真正起作用,可克隆类型需要使用适当的实现覆盖Object.clone()
。这意味着您的“克隆列表”将需要知道所包含的类型是否正确实现了clone()
,即使它能够做到这一点,也仅对一组非常有限的类型有用。clone()
的类型,执行list.add(elem.clone())
而不是list.add(elem)
相当简单。一种全新的列表,其中包含要点1中提到的警告,只是为了避免我们键入8个字符,这似乎不是一件非常有用的事情。答案 1 :(得分:2)
没有标准的方法来实现任何Collection的实现,这些实现会在添加对象时自动克隆其对象。
如果确实愿意,可以创建自己的List实现,并use reflection来克隆每个进出的对象。当出现这样的问题时,我绝不建议您在Collections库中实际创建自己的实现。我认为在这种情况下实际创建自己的实现的唯一原因是,如果您有其他一些将List或Collection作为参数的库,而您确实不希望该Collection的值发生突变。>
还可以选择不将可变数据实际存储在列表中。您始终可以为要存储在集合中的数据创建不可变的实现。如果可能,这是我会选择的选项。如果走这条路线,您仍然必须确保Data元素是不可变的,或者改为使用List<ImmutableData>
。使用List<ImmutableData>
可能不是一个坏主意,但是您可能必须在大多数方法签名中使用List<? extends Data>
。
它可能看起来像这样:
interface Data {
String getString();
MutableData toMutable();
}
class MutableData implements Data {
String getString() {...}
void setString(String s) {...}
Data toImmutable() {...}
MutableData clone() {...}
}
class ImmutableData implements Data {...}
如果您仍然想要克隆,但又不想使用反射或处理Cloneable接口所带来的所有问题,则可以创建自己的接口,该接口对于您的应用程序而言更为通用。