clone()方法是Object类中的一个方法,clone是穿件对象的四大方法之一(另外三个 new ,反射,发序列化),通过调用该方法,可以新建一个对象。那什么是深复制什么是浅复制呢?还是举例子来说比较直观。
首先是浅复制,反下面代码:
public class Student implements Cloneable{
private String studentName;
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getStudentName() {
return studentName;
}
public void setStudentName(String studentName) {
this.studentName = studentName;
}
protected Object clone() throws CloneNotSupportedException {
Student student = (Student) super.clone();
return student;
}
}
public static void main(String args[]){
Student student = new Student();
student.setAge(10);
student.setStudentName("xiaobai");
try {
Student s1 = (Student) student.clone();
System.out.println("student.studentName:"+student.getStudentName());
System.out.println("student.age:"+student.getAge());
System.out.println("s1.studentName:"+s1.getStudentName());
System.out.println("s1.age:"+s1.getAge());
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
打印运行输出结果:
student.studentName:xiaobai
student.age:10
s1.studentName:xiaobai
s1.age:10
student 和s1的内容完全一致,而且我们可以修改s1的值,而不会影响student的值。
验证一下:public static void main(String args[]){
Student student = new Student();
student.setAge(10);
student.setStudentName("xiaohong");
try {
Student s1 = (Student) student.clone();
s1.setStudentName("xiaohei");
System.out.println("student.studentName:"+student.getStudentName());
System.out.println("student.age:"+student.getAge());
System.out.println("s1.studentName:"+s1.getStudentName());
System.out.println("s1.age:"+s1.getAge());
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
运行结果:
student.studentName:xiaohong
student.age:10
s1.studentName:xiaohei
s1.age:10
需要注意clone方法在当前类没有实现Cloneable的情况下可能抛出CloneNotSupportedException,所以我们需要对该异常进行处理。以上的Student类中只有基本属性,这种拷贝被称为浅复制。
浅复制说完了再看深复制
如果对象中有其他对象的引用,使用浅复制无法完成对象的整个克隆,因为如果使用浅复制,只是对象的引用得到的拷贝,而两个引用是指向了同一个对象,对其中一个修改还是会影响到另外一个对象。这时我们需要引入深复制,深复制实现起来也比较简单,只需要对对象中的对象再次进行clone操作。
看下面代码:
public class Glasses implements Cloneable {
private String color;
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class Student implements Cloneable{
private String studentName;
private Glasses glasses;
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getStudentName() {
return studentName;
}
public void setStudentName(String studentName) {
this.studentName = studentName;
}
public Glasses getGlasses() {
return glasses;
}
public void setGlasses(Glasses glasses) {
this.glasses = glasses;
}
protected Object clone() throws CloneNotSupportedException {
Student student = (Student) super.clone();
student.glasses= (Glasses) glasses.clone();
return student;
}
}
如果想对Glasses进行拷贝,而不是仅仅克隆Glasses的引用,在clone方法中增加了student.glasses= (Glasses) glasses.clone();
验证一下:
public static void main(String args[]){
Student student = new Student();
student.setAge(10);
student.setStudentName("xiaobai");
Glasses glasses = new Glasses();
glasses.setColor("red");
student.setGlasses(glasses);
try {
Student s1 = (Student) student.clone();
s1.setStudentName("xiaohong");
s1.getGlasses().setColor("blue");
System.out.println("s1.color:"+s1.getGlasses().getColor());
System.out.println("student.color:"+student.getGlasses().getColor());
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
运行输出:
s1.color:blue
student.color:red
通过以上实例,可以看出student中Glasses被复制,修改s1中的color不会影响student中的color。