clone()
方法用于复制一个对象,该方法定义在java.lang.Object
类中,因此所有的类都拥有该方法。
protected native Object clone() throws CloneNotSupportedException;
下面看一个例子:
public class Address {
public String city;
public Address(String city) {
this.city = city;
}
}
public class Person {
public int age;
public Address address;
public Person(int age, Address address) {
this.age = age;
this.address = address;
}
}
public static void main(String[] args) throws CloneNotSupportedException {
Person source = new Person("name", new Address("Shanghai"));
Person copy = (Person) source.clone();
}
以上代码在运行时会抛出java.lang.CloneNotSupportedException
异常,这是因为Person
类没有实现Cloneable
接口。在我们做了如下修改后就能正确复制对象了。
public class Person implements Cloneable
clone()
方法在Object
中用protected
修饰,因此在子类中如果希望把该方法公开,那么在重写该方法时应该使用public
进行修饰。
// 在Person类中重写clone()方法
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
有关深复制和浅复制的概念可以前往这里进行了解。对于clone()
方法是一浅复制还是深复制,我们直接编码看一下:
public static void main(String[] args) throws CloneNotSupportedException {
Person source = new Person("name", new Address("Shanghai"));
Person copy = (Person) source.clone();
source.address.city = "Beijing";
System.out.println(copy.address.city); //此处打印“Beijing”
}
以上代码最后打印结果是“Beijing”,说明复制后的对象中的address
和源对象中的address
引用同一对象,因此clone()
是浅复制。
那我们能否修改clone()
方法以实现深复制呢?答案是肯定的。
@Override
public Object clone() throws CloneNotSupportedException {
Person copy = (Person) super.clone();
//针对对象类型的字段单独复制
copy.address = new Address(this.address.city);
return copy;
}
对于address
字段我们进行单独复制,甚至如果Address
类型实现了Cloneable
接口我们也可以直接调用address
的clone()
方法进行复制,这样就做到了深复制。
这里需要注意的是,如果address
字段被final
修饰,那么深复制就不可行了,因为我们无法在clone()
方法中对复制后的Person
对象的address
字段进行赋值。