Java防御副本
我见过这样编码的防御副本
void someMethod(Date d) {
myDate = new Date( d.getTime() );
}
但这对我来说没有意义,Java 中是否有一种方法可以在该对象的内存中创建相同的副本?
我已经读过 clone()
不会在所有情况下工作,但我不明白为什么。
I've seen defensive copies coded like this
void someMethod(Date d) {
myDate = new Date( d.getTime() );
}
But that doesn't make sense to me, isn't there a way in Java to create an identical copy in memory of that object?
I've read the clone()
will not work in all instances, but I don't understand why.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我可以尝试回答这个问题,但我只是抄袭乔什·布洛赫(Josh Bloch),所以这里有一个资源链接:
I could try to answer this, but I'd just be plagiarizing Josh Bloch, so here's a link to the resource instead:
clone()
仅在某些类中有意义地实现,因为克隆涉及 JVM 或编译器无法做出的许多决策(例如,浅复制与深复制)。有些人还认为 Java 中的整个概念被破坏了,因此很少被使用。然而,最终的结果是许多类无法克隆。在这些情况下,用户通过基于另一个对象生成和初始化一个对象来克隆它们。
但是,
Date
类实现了Cloneable
,因此与仅使用“复制构造函数”相比,在这种特定情况下并没有真正的好处。最好使用克隆的一种情况是当您使用类层次结构时。想象一下,您将一个数学表达式表示为表达式子类型的树,其中引用最外层表达式。
假设在本例中它是 Plus。您可以在对表达式的引用上调用克隆,但您真正得到的是 Plus 的新实例。对于构造函数,您实际上无法做到这一点,因为您的表达式可能是接口或抽象类。
clone()
is only implemented meaningfully in some classes, because there are a lot of decisions involved in cloning that the JVM or the compiler doesn't make for you (e.g., shallow vs. deep copying). Some would also argue that the whole concept in Java is broken and therefore rarely used.The end result, however, is that many classes cannot be cloned. In these cases, a user clones them by generating and initializing one object based on the other.
However, the
Date
class implementsCloneable
, so there isn't really a benefit in this specific case compared to just using the "copy constructor".One situation where cloning is preferable is when you are working with class hierarchies. Imagine you are representing a mathematical expression as a tree of Expression subtypes, where you reference the outermost expression.
Let's say that in this case it is a Plus. You would call clone on your reference to an Expression, but what you would really get is a new instance of Plus. With constructors you can't really do that because your Expression could be an interface or an abstract class.
没有简单的方法可以制作始终有效的相同副本。
克隆本应做到这一点,但并非所有类都实现了它,因此或多或少被破坏了。
另一种方法是序列化/反序列化,但并非所有类都支持序列化。
There is no simple way to make an identical copy that always works.
Clone was supposed to do that, but it is not implemented by all classes and thus more or less broken.
Another approach would be to serialize/deserialize, but serialization is also not supported by all classes.
从移动代码安全的角度来看,
clone
通常可以被覆盖。即使您不关心安全性,您也可以想象一个程序员“聪明”,导致您的代码中出现错误报告。
特别是
clone
将返回完全相同的运行时类型的期望也会导致实现问题。From a mobile code security point of view,
clone
can typically be overridden.Even if you don't care about security, you could imagine a programmer being "clever" causing a bug report in your code.
The expectation that particularly
clone
will return exactly the same runtime type also causes implementation problems.