我不明白克隆自定义对象的机制.例如:
public class Main{
public static void main(String [] args) {
Person person = new Person();
person.setFname("Bill");
person.setLname("Hook");
Person cloned = (Person)person.clone();
System.out.println(cloned.getFname() + " " + cloned.getLname());
}
}
class Person implements Cloneable{
private String fname;
private String lname;
public Object clone() {
Person person = new Person();
person.setFname(this.fname);
person.setLname(this.lname);
return person;
}
public void setFname(String fname) {
this.fname = fname;
}
public void setLname(String lname){
this.lname = lname;
}
public String getFname(){
return fname;
}
public String getLname() {
return lname;
}
}
Run Code Online (Sandbox Code Playgroud)
这个示例显示了正确的克隆方式,如书中所写.但是我可以在类名定义中删除implements Cloneable,并且我收到相同的结果.
所以我不明白Cloneable的提议以及为什么在类Object中定义了clone()方法?
Rin*_*nke 13
克隆方法旨在进行深层复制.确保您了解深拷贝和浅拷贝之间的区别.在您的情况下,复制构造函数可能是您想要的模式.在某些情况下,您无法使用此模式,例如,因为您正在为类X创建子类,并且您无法访问所需的X构造函数.如果X正确覆盖其克隆方法(如有必要),则可以按以下方式复制:
class Y extends X implements Cloneable {
private SomeType field; // a field that needs copying in order to get a deep copy of a Y object
...
@Override
public Y clone() {
final Y clone;
try {
clone = (Y) super.clone();
}
catch (CloneNotSupportedException ex) {
throw new RuntimeException("superclass messed up", ex);
}
clone.field = this.field.clone();
return clone;
}
}
Run Code Online (Sandbox Code Playgroud)
通常在覆盖克隆方法时:
super.clone()clone()也适用于任何子类时,不要包含throws子句(克隆模式的弱点;如果可能的话,make class final)super.clone()(克隆模式的另一个弱点,因为这些字段不能成为最终字段)(当所有超类都遵守契约时最终会调用的clone()方法Object)生成浅层副本并处理新对象的正确运行时类型.请注意在整个过程中如何调用构造函数.
如果您希望能够调用clone()实例,则实现该Cloneable接口并将该方法设为公共.如果您不希望能够在实例上调用它,但是您确实希望确保子类可以调用它们super.clone()并获得它们所需的内容,那么如果您的超类未声明它是公共的,则不要实现Cloneable并保留该方法protected已经.
克隆模式很难并且有很多陷阱.确保它是你需要的.考虑复制构造函数或静态工厂方法.
本clone()类Object不记忆,而不是调用类的构造方法的浅表副本.为了调用clone()任何不实现clone()自身的对象,您需要实现该Clonable接口.
如果重写该clone()方法,则不必实现该接口.
正如JavaDoc所说,这将导致异常:
class A {
private StringBuilder sb; //just some arbitrary member
}
...
new A().clone(); //this will result in an exception, since A does neither implement Clonable nor override clone()
Run Code Online (Sandbox Code Playgroud)
如果A在示例中实现Clonable调用clone()(Object版本)将导致A引用完全相同的 StringBuilder 的新实例,即sb对克隆实例的更改将导致sb对原始A实例中的更改.
这意味着浅拷贝,这是为什么通常更好地覆盖的一个原因clone().
编辑:正如旁注,使用返回类型协方差将使您的重写clone()更明确:
public Person clone() {
...
}
Run Code Online (Sandbox Code Playgroud)
JVM能够为您克隆对象,因此您不应该自己构建新人.只需使用此代码:
class Person implements Cloneable {
// ...
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
Run Code Online (Sandbox Code Playgroud)
要么
class Person implements Cloneable {
// ...
@Override
public Object clone() {
try {
return super.clone();
}
catch (CloneNotSupportedException e) {
throw new Error("Something impossible just happened");
}
}
}
Run Code Online (Sandbox Code Playgroud)
即使Person类是子类,这也会起作用,而您的克隆实现将始终创建Person的实例(例如,不是Employee的Employee实例).
| 归档时间: |
|
| 查看次数: |
48108 次 |
| 最近记录: |