Clone()vs Copy构造函数 - 在java中推荐

时间:2010-03-11 19:08:43

标签: java clone copy-constructor

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

6 个答案:

答案 0 :(得分:103)

克隆破了,所以不要使用它。

  

Object类的CLONE方法   这是一种有点神奇的方法   什么都没有纯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-javaeffective-cloning.aspx

答案 1 :(得分:53)

请注意clone()不能开箱即用。您必须实施Cloneable并覆盖clone()中的public方法。

有一些替代方案,这是更可取的(因为clone()方法有很多设计问题,如其他答案中所述),并且复制构造函数需要手动工作:

答案 2 :(得分:32)

clone()设计有几个错误(见this question),所以最好避免它。

Effective Java 2nd Edition,第11项:明智地覆盖克隆

  

考虑到与Cloneable相关的所有问题,可以说是安全的   其他接口不应该扩展它,以及那些类   为继承而设计(第17项)不应该实现它。因为   它的许多缺点,一些专家程序员只是选择永远不会   覆盖克隆方法,永远不要调用它,除非可能   复制数组。如果您设计了一个继承类,请注意if   你选择不提供一个行为良好的受保护克隆方法   子类不可能实现Cloneable。

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

  • 他们不依赖于易于冒险的语言外对象创建机制
  • 他们不要求无法执行的遵守精简文件的惯例
  • 他们与正确使用最终字段不会发生冲突
  • 他们不会抛出不必要的检查异常
  • 他们不需要演员表。

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

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

答案 3 :(得分:18)

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

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

答案 4 :(得分:3)

另见:How to properly override clone method?。克隆在Java中被打破了,如此努力以使其正确,即使它确实存在也没有提供太多,所以它并不值得麻烦。< / p>

答案 5 :(得分:2)

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

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

当然,如果更多的库(例如 - 集合)是不可变的,那么这个“复制”任务就会消失。但是后来我们开始用“类不变量”而不是verdammt“bean”模式设计Java程序(制作一个破碎的对象并变异直到好[足够])。