Clone() 与 Copy 构造函数——在 java 中推荐使用
java中的克隆方法与复制构造函数。哪一个是正确的解决方案。每个案例在哪里使用?
clone method vs copy constructor in java. which one is correct solution. where to use each case?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
克隆已损坏,因此请勿使用它。
喜欢复制对象的方法
阅读更多
http://adtmag.com/articles/2000/01/18 / effective-java effective-cloning.aspx
Clone is broken, so dont use it.
Prefer a method that copies the object
Read more
http://adtmag.com/articles/2000/01/18/effective-javaeffective-cloning.aspx
请记住,
clone()
不能开箱即用。您必须实现Cloneable
并重写public
中的clone()
方法。有一些更好的替代方案(因为
clone()
方法有很多设计问题,如其他答案中所述),并且复制构造函数需要手动工作:< a href="http://commons.apache.org/beanutils/v1.8.2/apidocs/org/apache/commons/beanutils/BeanUtils.html" rel="noreferrer">
BeanUtils.cloneBean(原始)< /code> 创建一个浅克隆,类似于
Object.clone()
创建的克隆。 (此类来自 commons-beanutils)SerializationUtils.clone(original)
创建深度克隆。 (即克隆整个属性图,而不仅仅是第一级)(来自 commons-lang),但所有类都必须实现Serialized
Java 深度克隆库提供深度克隆,无需实现
Serialized
Have in mind that
clone()
doesn't work out of the box. You will have to implementCloneable
and override theclone()
method making inpublic
.There are a few alternatives, which are preferable (since the
clone()
method has lots of design issues, as stated in other answers), and the copy-constructor would require manual work:BeanUtils.cloneBean(original)
creates a shallow clone, like the one created byObject.clone()
. (this class is from commons-beanutils)SerializationUtils.clone(original)
creates a deep clone. (i.e. the whole properties graph is cloned, not only the first level) (from commons-lang), but all classes must implementSerializable
Java Deep Cloning Library offers deep cloning without the need to implement
Serializable
clone() 的设计有几个错误(请参阅这个问题),所以它是最好避免它。
来自 Effective Java 第 2 版,第 11 项:明智地覆盖克隆
本书还描述了复制构造函数相对于 Cloneable/clone 的许多优点。
所有标准集合都有复制构造函数。使用它们。
clone() was designed with several mistakes (see this question), so it's best to avoid it.
From Effective Java 2nd Edition, Item 11: Override clone judiciously
This book also describes the many advantages copy constructors have over Cloneable/clone.
All standard collections have copy constructors. Use them.
请记住,复制构造函数将类类型限制为复制构造函数的类型。考虑这个例子:
如果
person
可以是Person
的子类(或者如果Person
是一个接口),则此方法不起作用。这就是克隆的全部要点,它可以在运行时动态克隆正确的类型(假设克隆被正确实现)。或者
现在
person
可以是任何类型的Person
,假设clone
已正确实现。Keep in mind that the copy constructor limits the class type to that of the copy constructor. Consider the example:
This doesn't work if
person
could be a subclass ofPerson
(or ifPerson
is an interface). This is the whole point of clone, is that it can can clone the proper type dynamically at runtime (assuming clone is properly implemented).or
Now
person
can be any type ofPerson
assuming thatclone
is properly implemented.另请参阅:如何正确覆盖克隆方法?。克隆在 Java 中被破坏了,要得到它非常困难,而且即使做到了也没有真正提供太多,所以它并不值得这么麻烦。
See also: How to properly override clone method?. Cloning is broken in Java, it's so hard to get it right, and even when it does it doesn't really offer much, so it's not really worth the hassle.
非常悲伤:Cloneable/clone 和构造函数都不是很好的解决方案:我不想知道实现类! (例如 - 我有一个地图,我想复制它,使用相同的隐藏 MumbleMap 实现)我只想制作一个副本(如果支持的话)。但是,可惜的是,Cloneable 没有clone 方法,因此您无法安全地进行类型转换来调用clone()。
无论最好的“复制对象”库是什么,Oracle 都应该将其作为下一个 Java 版本的标准组件(除非它已经存在,隐藏在某处)。
当然,如果更多的库(例如集合)是不可变的,那么这个“复制”任务就会消失。但随后我们将开始使用“类不变量”之类的东西来设计 Java 程序,而不是 verdammt“bean”模式(创建一个损坏的对象并进行变异,直到好[足够])。
Great sadness: neither Cloneable/clone nor a constructor are great solutions: I DON'T WANT TO KNOW THE IMPLEMENTING CLASS!!! (e.g. - I have a Map, which I want copied, using the same hidden MumbleMap implementation) I just want to make a copy, if doing so is supported. But, alas, Cloneable doesn't have the clone method on it, so there is nothing to which you can safely type-cast on which to invoke clone().
Whatever the best "copy object" library out there is, Oracle should make it a standard component of the next Java release (unless it already is, hidden somewhere).
Of course, if more of the library (e.g. - Collections) were immutable, this "copy" task would just go away. But then we would start designing Java programs with things like "class invariants" rather than the verdammt "bean" pattern (make a broken object and mutate until good [enough]).