Clone() 与复制构造函数 - 在 java 中推荐[重复]

问题描述 投票:0回答:6

java中的克隆方法与复制构造函数。哪一个是正确的解决方案。每个案例在哪里使用?

java clone copy-constructor
6个回答
121
投票

克隆已损坏,所以不要使用它。

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


58
投票

请记住,

clone()
不能开箱即用。您必须实现
Cloneable
并重写
clone()
中的
public
方法。

有一些更好的替代方案(因为

clone()
方法有很多设计问题,如其他答案中所述),并且复制构造函数需要手动工作:


34
投票

clone() 的设计有几个错误(参见这个问题),所以最好避免它。

来自 Effective Java 第二版,第 11 条:明智地覆盖克隆

考虑到与 Cloneable 相关的所有问题,可以肯定地说 其他接口不应扩展它,并且类 为继承而设计(第 17 条)不应实现它。由于 它有很多缺点,一些专家程序员干脆选择不这样做 覆盖克隆方法并且永远不会调用它,除非,也许, 复制数组。如果您设计一个用于继承的类,请注意,如果 您选择不提供行为良好的受保护克隆方法,它 子类不可能实现 Cloneable。

本书还描述了复制构造函数相对于 Cloneable/clone 的许多优点。

  • 它们不依赖于有风险的语言外对象创建机制
  • 他们不要求遵守不可执行的、记录薄弱的约定
  • 它们与最终字段的正确使用并不冲突
  • 他们不会抛出不必要的检查异常
  • 他们不需要演员表。

所有标准集合都有复制构造函数。使用它们。

List<Double> original = // some list
List<Double> copy = new ArrayList<Double>(original);

19
投票

请记住,复制构造函数将类类型限制为复制构造函数的类型。考虑这个例子:

// 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
已正确实现。


3
投票

另请参阅:如何正确重写克隆方法?。克隆在 Java 中被破坏了,想要做到正确是非常困难,而且即使做到了,也没有真正提供多少,所以它并不值得这么麻烦。


2
投票

非常悲伤:Cloneable/clone 和构造函数都不是很好的解决方案:我不想知道实现类! (例如 - 我有一个地图,我想复制它,使用相同的隐藏 MumbleMap 实现)我只想制作一个副本(如果支持的话)。 但是,可惜的是,Cloneable 没有 clone 方法,因此您无法安全地进行类型转换来调用clone()。

无论最好的“复制对象”库是什么,Oracle 都应该将其作为下一个 Java 版本的标准组件(除非它已经存在,隐藏在某处)。

当然,如果更多的库(例如集合)是不可变的,这个“复制”任务就会消失。 但随后我们会开始使用“类不变量”之类的东西来设计 Java 程序,而不是 verdammt“bean”模式(创建一个损坏的对象并进行变异,直到变得足够好)。

© www.soinside.com 2019 - 2024. All rights reserved.