【发布时间】:2019-06-03 16:26:46
【问题描述】:
是否有实现 List 接口并在元素添加到列表时克隆元素的 Java 类?这样做的目的是保持将此列表封装为对象。
当然,自己写一个很容易,例如,将 ArrayList 封装在另一个类中,然后在实现 add 和 get 方法时调用 clone 方法。但是,我想我会问 Java 是否已经提供了这样一个类,并且可能会为自己节省一些繁琐的编码。
【问题讨论】:
标签: java list class encapsulation
是否有实现 List 接口并在元素添加到列表时克隆元素的 Java 类?这样做的目的是保持将此列表封装为对象。
当然,自己写一个很容易,例如,将 ArrayList 封装在另一个类中,然后在实现 add 和 get 方法时调用 clone 方法。但是,我想我会问 Java 是否已经提供了这样一个类,并且可能会为自己节省一些繁琐的编码。
【问题讨论】:
标签: java list class encapsulation
我怀疑一个存在,有几个原因:
Object.clone() 仅适用于实现 @Cloneable 的类型;当它工作时,它只做一个浅拷贝(例如,如果对象有一个List 字段,它会克隆对列表对象的引用,而不是它的元素);打败了自己的目的。 Info about Java cloning problems。因此,要使克隆真正起作用,可克隆类型需要用正确的实现覆盖Object.clone()。这意味着您的“克隆列表”需要知道所包含的类型是否正确实现了clone(),即使它设法做到了,它也只对非常有限的一组类型有用。clone() 的类型,使用list.add(elem.clone()) 而不是list.add(elem) 相当简单。带有第 1 点中提到的警告的全新类型的列表,只是为了让我们免于输入 8 个字符,这似乎不是一件很有用的东西。【讨论】:
没有标准的方法来实现任何 Collection,在添加对象时自动克隆其对象。
如果你真的想要,你可以创建你自己的 List 实现和use reflection 来克隆每个进出的对象。当提出这样的问题时,我从不建议您在 Collections 库中实际创建自己的实现。我认为在这种情况下实际创建自己的实现的唯一原因是,如果您有一些其他库将 List 或 Collection 作为参数,并且您真的不希望该 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 接口带来的所有问题,您可以创建自己的接口,该接口更适合您的应用程序。
【讨论】: