克隆方法与 java 中的复制建构子,哪一个是正确的解决方案,在哪里使用?
克隆人坏了,所以不要用它。
Object 类的克隆方法 是一种有点神奇的方法 任何纯 Java 方法都无法做到的事情 做: 它产生一个完全相同的副本 它的目标。它一直存在于 原始对象超类,因为 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
请记住,clone()不是开箱即用的。您必须实现 Cloneable并覆盖 public中的 clone()方法。
clone()
Cloneable
public
有一些更好的替代方法(因为 clone()方法有很多设计问题,如其他答案所述) ,并且复制构造函数将需要手工操作:
BeanUtils.cloneBean(original) 创建一个浅克隆,就像 Object.clone()创建的那个一样(这个类来自 公共资源-美人鱼)
BeanUtils.cloneBean(original)
Object.clone()
SerializationUtils.clone(original) 创建一个深度克隆。(例如,从 Commons-lang克隆整个属性图,而不仅仅是第一层) ,但是所有类都必须实现 Serializable
SerializationUtils.clone(original)
Serializable
Java 深度克隆库 提供了无需实现 Serializable的深度克隆
参见: 如何正确重写克隆方法?。克隆在 Java 中被破坏了,它是 太难了来做正确的,甚至当它做 没什么用的时候,所以它真的不值得这么麻烦。
请记住,复制建构子将类的类型限制为复制建构子的类型:
// Need to clone person, which is type Person Person clone = new Person(person);
如果 person可能是 Person的子类(或者如果 Person是一个接口) ,那么这就不起作用了。这就是克隆的全部意义所在,它可以在运行时动态地克隆适当的类型(假设克隆得到了适当的实现)。
person
Person
Person clone = (Person)person.clone();
或者
Person clone = (Person)SomeCloneUtil.clone(person); // See Bozho's answer
现在,假设 clone得到了正确的实现,那么 person可以是任何类型的 Person。
clone
克隆()的设计有几个错误(参见 这个问题) ,因此最好避免它。
来自 有效的 Java 第二版第11项: 明智地覆盖克隆
考虑到与克隆人有关的所有问题,可以肯定地说 其他接口不应该扩展它,而类 为继承而设计的(第17项)不应实现它 它的许多缺点,一些专家程序员只是选择从来没有 覆盖克隆方法,并且永远不要调用它,除非,也许,调用 如果为继承设计类,请注意 如果您选择不提供行为良好的受保护的克隆方法,则 子类将不可能实现 Cloneable。
本书还描述了复制构造函数相对于可克隆/克隆构造函数的许多优势。
所有标准集合都有复制构造函数。使用它们。
List<Double> original = // some list List<Double> copy = new ArrayList<Double>(original);
巨大的悲哀: 无论是可克隆/克隆还是构造函数都不是伟大的解决方案: 我不想知道实现类! ! !(例如-我有一个地图,我想复制,使用相同的隐藏 MumbleMap 实现)我只是想做一个副本,如果这样做是支持的。但是,唉,Cloneable 上没有 Cloneable 方法,因此您无法安全地对其进行类型强制转换,从而无法调用 clone()。
无论最好的“复制对象”库是什么,Oracle 都应该让它成为下一个 Java 版本的标准组件(除非它已经是了,隐藏在某个地方)。
当然,如果更多的库(例如-Collection)是不可变的,那么这个“复制”任务就会消失。但是接下来我们将开始使用“类不变量”而不是该死的“ bean”模式来设计 Java 程序(创建一个破碎的对象并进行变异直到足够好)。