java中的克隆方法与复制构造函数。哪一个是正确的解决方案。每个案例在哪里使用?
克隆已损坏,所以不要使用它。
Object类的克隆方法 是一种有点神奇的方法 纯 Java 方法无法做到的事情 do:它生成相同的副本 它的对象。它已经出现在 原始的 Object 超类 Java 的 Beta 发布日 编译器*;它,就像所有古代的 魔法,需要适当的 咒语以防止该咒语 没想到事与愿违
更喜欢复制对象的方法
Foo copyFoo (Foo foo){
Foo f = new Foo();
//for all properties in FOo
f.set(foo.get());
return f;
}
了解更多 http://adtmag.com/articles/2000/01/18/ effective-java effective-cloning.aspx
请记住,
clone()
不能开箱即用。您必须实现 Cloneable
并重写 clone()
中的 public
方法。
有一些更好的替代方案(因为
clone()
方法有很多设计问题,如其他答案中所述),并且复制构造函数需要手动工作:
BeanUtils.cloneBean(original)
创建一个浅克隆,就像 Object.clone()
创建的克隆一样。 (这个类来自commons-beanutils)
SerializationUtils.clone(original)
创建深度克隆。 (即整个属性图被克隆,不仅仅是第一级)(来自commons-lang),但所有类都必须实现Serializable
Java深度克隆库提供深度克隆,无需实现
Serializable
clone() 的设计有几个错误(参见这个问题),所以最好避免它。
来自 Effective Java 第二版,第 11 条:明智地覆盖克隆
考虑到与 Cloneable 相关的所有问题,可以肯定地说 其他接口不应扩展它,并且类 为继承而设计(第 17 条)不应实现它。由于 它有很多缺点,一些专家程序员干脆选择不这样做 覆盖克隆方法并且永远不会调用它,除非,也许, 复制数组。如果您设计一个用于继承的类,请注意,如果 您选择不提供行为良好的受保护克隆方法,它 子类不可能实现 Cloneable。
本书还描述了复制构造函数相对于 Cloneable/clone 的许多优点。
所有标准集合都有复制构造函数。使用它们。
List<Double> original = // some list
List<Double> copy = new ArrayList<Double>(original);
请记住,复制构造函数将类类型限制为复制构造函数的类型。考虑这个例子:
// Need to clone person, which is type Person
Person clone = new Person(person);
如果
person
可以是 Person
的子类(或者 Person
是一个接口),则此方法不起作用。这就是克隆的全部要点,它可以在运行时动态克隆正确的类型(假设克隆已正确实现)。
Person clone = (Person)person.clone();
或
Person clone = (Person)SomeCloneUtil.clone(person); // See Bozho's answer
现在
person
可以是任何类型的 Person
假设 clone
已正确实现。
另请参阅:如何正确重写克隆方法?。克隆在 Java 中被破坏了,想要做到正确是非常困难,而且即使做到了,也没有真正提供多少,所以它并不值得这么麻烦。
非常悲伤:Cloneable/clone 和构造函数都不是很好的解决方案:我不想知道实现类! (例如 - 我有一个地图,我想复制它,使用相同的隐藏 MumbleMap 实现)我只想制作一个副本(如果支持的话)。 但是,可惜的是,Cloneable 没有 clone 方法,因此您无法安全地进行类型转换来调用clone()。
无论最好的“复制对象”库是什么,Oracle 都应该将其作为下一个 Java 版本的标准组件(除非它已经存在,隐藏在某处)。
当然,如果更多的库(例如集合)是不可变的,这个“复制”任务就会消失。 但随后我们会开始使用“类不变量”之类的东西来设计 Java 程序,而不是 verdammt“bean”模式(创建一个损坏的对象并进行变异,直到变得足够好)。