Java防御性拷贝

Java防御性拷贝,java,theory,defensive-programming,Java,Theory,Defensive Programming,我见过这样的防御性副本 void方法(日期d){ myDate=新日期(d.getTime()); } 但这对我来说毫无意义,Java中是否有办法在该对象的内存中创建相同的副本 我已经阅读了clone()并非在所有情况下都有效,但我不明白为什么。我可以尝试回答这个问题,但我只是在剽窃Josh Bloch,所以这里有一个指向资源的链接: 比尔·维纳斯:在你的书中,你建议使用复制构造函数,而不是实现Cloneable和编写clone。你能详细说明一下吗 乔什·布洛赫:如果你读过我书中有关克隆的内容

我见过这样的防御性副本

void方法(日期d){
myDate=新日期(d.getTime());
}
但这对我来说毫无意义,Java中是否有办法在该对象的内存中创建相同的副本


我已经阅读了
clone()
并非在所有情况下都有效,但我不明白为什么。

我可以尝试回答这个问题,但我只是在剽窃Josh Bloch,所以这里有一个指向资源的链接:

比尔·维纳斯:在你的书中,你建议使用复制构造函数,而不是实现
Cloneable
和编写
clone
。你能详细说明一下吗

乔什·布洛赫:如果你读过我书中有关克隆的内容,特别是如果你读过字里行间的内容,你就会知道我认为克隆已经彻底崩溃了。有一些设计缺陷,其中最大的缺陷是
Cloneable
接口没有
clone
方法。这意味着它根本不起作用:使某个东西
可克隆
并没有说明你可以用它做什么。相反,它说的是它可以在内部做些什么。它表示,如果通过反复调用
super.clone
而最终调用
Object
clone
方法,此方法将返回原始的字段副本

但是它没有说明你可以对实现
Cloneable
接口的对象做什么,这意味着你不能进行多态
clone
操作。如果我有一个
Cloneable
数组,您可能会认为我可以运行该数组并克隆每个元素以生成数组的深度副本,但我不能。您不能将某些内容强制转换为
Cloneable
并调用
clone
方法,因为
Cloneable
没有公共的
clone
方法,
对象也没有。如果您尝试强制转换到
Cloneable
并调用
clone
方法,编译器会说您正在尝试调用对象上受保护的
clone
方法

事实上,您没有通过实现
Cloneable
和提供公共
clone
方法而向客户提供任何功能,而不是复制功能。如果您提供了一个具有不同名称的复制操作,并且没有实现
Cloneable
,那么这并不比您得到的更好。这基本上就是使用复制构造函数所做的。复制构造函数方法有几个优点,我在书中讨论过。一个很大的优点是,可以使副本具有与原件不同的表示形式。例如,您可以将
LinkedList
复制到
ArrayList

对象
克隆
方法非常棘手。它基于字段副本,并且是“非语言的”。它创建一个对象而不调用构造函数。不能保证它保留构造函数建立的不变量。多年来,Sun内外都出现了很多bug,这是因为如果你只是重复调用
super.clone
,直到你克隆了一个对象,你就得到了该对象的浅拷贝。克隆通常与要克隆的对象共享状态。如果该状态是可变的,则没有两个独立的对象。如果修改其中一个,其他的也会更改。突然间,你会有随机行为

我已经很少使用可克隆的东西了。我经常在具体类上提供一个公共的
clone
方法,因为人们期望它。我没有抽象类实现
Cloneable
,也没有接口扩展它,因为我不会把实现
Cloneable
的负担放在所有扩展(或实现)抽象类(或接口)的类上。这是一个真正的负担,几乎没有好处

道格·利亚走得更远。他告诉我,除了复制数组,他不再使用
clone
。您应该使用
clone
来复制阵列,因为这通常是最快的方法。但是Doug的类型不再实现
Cloneable
。他已经放弃了。我认为这不是不合理的

可耻的是,
Cloneable
被破坏了,但它确实发生了。最初的JavaAPI是在一个紧迫的期限内完成的,以满足即将关闭的市场窗口。最初的Java团队做了令人难以置信的工作,但并非所有的API都是完美的<代码>可克隆性
是一个弱点,我认为人们应该意识到它的局限性


我可以试着回答这个问题,但我只是在抄袭Josh Bloch,所以这里有一个指向资源的链接:

比尔·维纳斯:在你的书中,你建议使用复制构造函数,而不是实现
Cloneable
和编写
clone
。你能详细说明一下吗

乔什·布洛赫:如果你读过我书中有关克隆的内容,特别是如果你读过字里行间的内容,你就会知道我认为克隆已经彻底崩溃了。有一些设计缺陷,其中最大的缺陷是
Cloneable
接口没有
clone
方法。这意味着它根本不起作用:使某个东西
可克隆
并没有说明你可以用它做什么。相反,它说的是它可以在内部做些什么。它表示,如果通过反复调用
super.clone
而最终调用
Object
clone
方法,此方法将返回原始的字段副本

但是它没有说明你可以对实现
Cloneable
接口的对象做什么,这意味着你不能进行多态
clone
操作。如果我有一个数组
@Override public Date clone() {
    return this; // Ha!
}