Clone()vs Copy构造函数-在java中建议使用

Clone()vs Copy构造函数-在java中建议使用,java,clone,copy-constructor,Java,Clone,Copy Constructor,java中的克隆方法与复制构造函数。哪一个是正确的解决方案。在哪里使用每个案例?克隆已损坏,因此不要使用它 对象类的克隆方法 这是一种神奇的方法 任何纯Java方法都做不到的事情 do:它生成一个相同的 它的目标。它已经出现在 自 Java测试版发布日 编译器*;它就像所有古代的东西一样 魔法,需要适当的 咒语,以防止咒语 出人意料地适得其反 首选复制对象的方法 Foo copyFoo (Foo foo){ Foo f = new Foo(); //for all properties

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

克隆已损坏,因此不要使用它

对象类的克隆方法 这是一种神奇的方法 任何纯Java方法都做不到的事情 do:它生成一个相同的 它的目标。它已经出现在 自 Java测试版发布日 编译器*;它就像所有古代的东西一样 魔法,需要适当的 咒语,以防止咒语 出人意料地适得其反

首选复制对象的方法

Foo copyFoo (Foo foo){
  Foo f = new Foo();
  //for all properties in FOo
  f.set(foo.get());
  return f;
}
阅读更多

请记住,
clone()
不是现成的。您必须实现
Cloneable
并重写
public
中的
clone()
方法

有几个备选方案更可取(因为
clone()
方法有很多设计问题,如其他答案中所述),复制构造函数需要手动操作:

  • 创建一个浅克隆,就像由
    Object.clone()
    创建的一样。(本课程来自)

  • 创建深度克隆。(即,克隆整个属性图,不仅克隆第一级)(from),而且所有类都必须实现
    Serializable

  • 提供深度克隆,无需实现
    Serializable


另请参见:。在Java中,克隆是被破坏的,很难正确地实现它,即使这样做了,它也不能提供太多的功能,因此不值得这么麻烦。

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

// Need to clone person, which is type Person
Person clone = new Person(person);
如果
person
可以是
person
的子类(或者如果
person
是一个接口),则这不起作用。这就是克隆的全部意义,它可以在运行时动态克隆正确的类型(假设克隆正确实现)

现在,
person
可以是任何类型的
person
,前提是
clone
的实现是正确的。

clone()的设计有几个错误(请参阅),因此最好避免它

Person clone = (Person)person.clone();
从,第11项:明智地覆盖克隆

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

本书还描述了复制构造函数相对于可克隆/克隆的许多优势

  • 他们不依赖于有风险的语言外物体创造机制
  • 他们不要求不可强制执行地遵守记录很少的约定
  • 它们与final字段的正确使用没有冲突
  • 它们不会抛出不必要的已检查异常
  • 他们不需要石膏
所有标准集合都有副本构造函数。使用它们

List<Double> original = // some list
List<Double> copy = new ArrayList<Double>(original);
List original=//一些列表
列表副本=新阵列列表(原件);

巨大的悲哀:可克隆/克隆和构造函数都不是很好的解决方案:我不想知道实现类!!!(例如,我有一个地图,我想使用相同的隐藏MumbleMap实现复制它)如果支持的话,我只想复制一个。但是,遗憾的是,Cloneable上没有clone方法,因此您无法安全地键入cast来调用clone()

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


当然,如果库的更多部分(如集合)是不可变的,那么这个“复制”任务就会消失。但是,接下来我们将开始使用“类不变量”而不是verdammt“bean”模式来设计Java程序(创建一个破碎的对象,并进行变异,直到性能达到[足够好]。

不惜一切代价避免
clone
并采用您自己的复制解决方案。复制构造函数比object.clone()更好因为他们不强迫我们实现任何接口或抛出任何异常,但如果需要,我们肯定可以做到,不需要任何强制转换,不要求我们依赖未知的对象创建机制,不要求父类遵循任何约定或实现任何东西,允许我们修改最终字段,允许我们完全控制对象的创建,我们可以在其中编写初始化逻辑。阅读更多,嗯,克隆没有被破坏。你认为这是为什么?如果这是因为如果不重写它,它就不能工作,那么,这就是它的契约。@Bozho,阅读有效的Java第二版,Bloch解释得很好。除了克隆数组(),Doug Lea甚至不再使用
clone()
。我真的不明白为什么克隆不能更简单。这是一种选择吗?或者,在一般情况下,这背后确实存在着严重的问题?@polygene我也没有使用
clone()
,这就是我建议使用beanutils的原因。但我的观点是,可以使用
clone()
,尽管这是“明智的”。在简单的情况下,它工作得相当好。因此,让我们结束汽车比喻-这就像说,俄罗斯汽车的工作。我承认我还没有读过有效的Java,但我要说的是,Cloneable作为一个接口有其优势。也就是说,您可以将泛型类和函数的参数限制为只接受实现可克隆的类,然后只调用clone()。没有它,我不相信有一个(好的)方法来执行t
List<Double> original = // some list
List<Double> copy = new ArrayList<Double>(original);