Boz*_*zho 152
你应该知道的第一件事Cloneable
是 - 不要使用它.
用Cloneable
正确的方法实现克隆是非常困难的,并且努力是不值得的.
而不是使用其他选项,如apache-commons SerializationUtils
(深度克隆)或BeanUtils
(浅层克隆),或者只使用复制构造函数.
请参阅此处了解Josh Bloch关于克隆的观点Cloneable
,这解释了该方法的许多缺点.(Joshua Bloch是Sun的一名员工,领导了许多Java功能的开发.)
Luk*_*man 39
不幸的是,Cloneable本身只是一个标记接口,它是:它没有定义clone()方法.
做的是改变受保护的Object.clone()方法的行为,该方法将为不实现Cloneable的类抛出CloneNotSupportedException,并为那些执行成员的类执行浅层复制.
即使这是您正在寻找的行为,您仍然需要实现自己的clone()方法才能将其公开.
在实现你自己的clone()时,我们的想法是从super.clone()创建的对象开始,它保证是正确的类,然后在浅副本不是什么的情况下再做任何其他字段.你要.从clone()调用构造函数会有问题,因为如果子类想要添加自己的附加可克隆逻辑,这会破坏继承; 如果是调用super.clone(),在这种情况下会得到错误类的对象.
这种方法绕过了构造函数中可能定义的任何逻辑,这可能会产生问题.
另一个问题是,任何忘记覆盖clone()的子类都会自动继承默认的浅拷贝,这可能不是你想要的可变状态(现在将在源和副本之间共享).
大多数开发人员出于这些原因不使用Cloneable,而只是实现了一个复制构造函数.
有关Cloneable的更多信息和潜在缺陷,我强烈推荐Joshua Bloch撰写的Effective Java一书
Vla*_*nov 11
所以,明智地使用Cloneable.与您为完成所有事情所需的努力相比,它没有给您足够的好处.
克隆是一种基本的编程范例.Java可能在很多方面实现得很差这一事实并没有减少对克隆的需求.并且,很容易实现克隆,无论你希望它能够工作,浅薄,深入,混合,等等.您甚至可以使用名称clone作为函数,如果愿意,也不要实现Cloneable.
假设我有类A,B和C,其中B和C是从A派生的.如果我有类型A的对象列表,如下所示:
ArrayList<A> list1;
Run Code Online (Sandbox Code Playgroud)
现在,该列表可以包含A,B或C类型的对象.您不知道对象是什么类型.所以,你不能像这样复制列表:
ArrayList<A> list2 = new ArrayList<A>();
for(A a : list1) {
list2.add(new A(a));
}
Run Code Online (Sandbox Code Playgroud)
如果对象实际上是B或C类型,则无法获得正确的副本.而且,如果A是抽象的呢?现在,有人建议:
ArrayList<A> list2 = new ArrayList<A>();
for(A a : list1) {
if(a instanceof A) {
list2.add(new A(a));
} else if(a instanceof B) {
list2.add(new B(a));
} else if(a instanceof C) {
list2.add(new C(a));
}
}
Run Code Online (Sandbox Code Playgroud)
这是一个非常非常糟糕的主意.如果添加新的派生类型怎么办?如果B或C在另一个包中并且您在本课程中无法访问它们怎么办?
你想做的是:
ArrayList<A> list2 = new ArrayList<A>();
for(A a : list1) {
list2.add(a.clone());
}
Run Code Online (Sandbox Code Playgroud)
很多人都说明了为什么克隆的基本Java实现存在问题.但是,它很容易克服这种方式:
在A班:
public A clone() {
return new A(this);
}
Run Code Online (Sandbox Code Playgroud)
在B班:
@Override
public B clone() {
return new B(this);
}
Run Code Online (Sandbox Code Playgroud)
在C级:
@Override
public C clone() {
return new C(this):
}
Run Code Online (Sandbox Code Playgroud)
我没有实现Cloneable,只是使用相同的函数名称.如果您不喜欢,请将其他名称命名.
A)克隆复制构造函数没有很多优点.可能最大的一个是能够创建完全相同动态类型的新对象(假设声明的类型是可克隆的并且具有公共克隆方法).
B)默认克隆创建一个浅拷贝,除非克隆实现改变了,否则它将保持浅拷贝.这可能很困难,尤其是如果您的班级有最终字段
Bozho是对的,克隆可能很难做对.复制构造函数/工厂将满足大多数需求.
归档时间: |
|
查看次数: |
69239 次 |
最近记录: |