Java列表,添加后会克隆元素

时间:2019-06-03 16:26:46

标签: java list class encapsulation

是否存在一个Java类,该类实现List接口并在将元素添加到列表时克隆这些元素?这样做的目的是保留将此列表封装为对象。

当然,写一个我自己很容易,例如,获取ArrayList并将其包装在另一个类中,然后在实现add和get方法时调用clone方法。但是,我想问一下Java是否已经提供了这样的类,并可能节省一些繁琐的编码。

2 个答案:

答案 0 :(得分:4)

我怀疑一个人存在,原因有两个:

  1. 该列表应如何克隆元素? Object.clone()仅适用于实现@Cloneable的类型;并且当它起作用时,它只会进行浅表复制(例如,如果对象具有List字段,它将克隆对列表对象的引用,但不克隆其元素);达到自己的目的。 Info about Java cloning problems。因此,为了使克隆真正起作用,可克隆类型需要使用适当的实现覆盖Object.clone()。这意味着您的“克隆列表”将需要知道所包含的类型是否正确实现了clone(),即使它能够做到这一点,也仅对一组非常有限的类型有用。
  2. 对于实际实现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接口所带来的所有问题,则可以创建自己的接口,该接口对于您的应用程序而言更为通用。