clone深拷貝和淺拷貝
前言
clone是Object類的一個本地方法,Object類預設使用的是淺拷貝,如果想要實現深拷貝,需要去實現Cloneable介面,並重寫clone方法。
淺拷貝是指:當物件的屬性是基本資料型別時,會複製屬性及值,當物件的屬性有引用型別的時候,會把當前屬性引用複製。
深拷貝是指:當物件的屬性是基本資料型別時,會複製屬性及值,當物件的屬性有引用型別的時候,會把當前屬性引用的物件再複製一份。
區別就是:當需要clone的物件的屬性都是基本資料型別,深拷貝淺拷貝一樣,當需要clone的物件的屬性有引用型別的時候,淺拷貝直接把引用地址複製過去,深拷貝會把引用的物件再複製一份。
下面是例子:
淺拷貝
public class Test{
public static void main(String[] args) throws CloneNotSupportedException{
Professor p1=new Professor();
p1.setName("zhang");
p1.setAge(44);
Student s1=new Student();
s1.setName("Xiao Ming");
s1.setAge(15);
s1.setProfessor(p1);
System.out.println(s1);
Student s2=(Student) s1.clone();//克隆s1
Professor p2=s2.getProfessor();//這裡其實獲取的是p1的引用
//其實這裡修改的也是p1的屬性
p2.setName("Li");
p2.setAage(55);
s2.setProfessor(p2);
s2.setAge(88);//這裡是基本資料型別
s2.setName("Wu");//這裡是基本資料型別
System.out.println("修改前 :"+s1);
System.out.println("修改後 :"+s2);
}
}
class Student implements{
private String name;
private int age;
private Professor professor;
....set、get方法
...toString方法
@Override
protected Object clone()throws CloneNotSupportedException{
return super.clone();
}
}
class Professor {
private String name;
private int age;
...set、get方法
...toString方法
}
發現問題,當修改p2的時候,p1也跟著變了,是因為p1和p2指向的是同一個物件,所以clone的是引用。
深拷貝
public class Test{
public static void main(String[] args) throws CloneNotSupportedException{
Professor p1=new Professor();
p1.setName("zhang");
p1.setAge(44);
Student s1=new Student();
s1.setName("Xiao Ming");
s1.setAge(15);
s1.setProfessor(p1);
System.out.println(s1);
Student s2=(Student) s1.clone();//克隆s1
Professor p2=s2.getProfessor();//這裡其實獲取的是p1的引用
//其實這裡修改的也是p1的屬性
p2.setName("Li");
p2.setAage(55);
s2.setProfessor(p2);
s2.setAge(88);//這裡是基本資料型別
s2.setName("Wu");//這裡是基本資料型別
System.out.println("修改前 :"+s1);
System.out.println("修改後 :"+s2);
}
}
class Student implements{
private String name;
private int age;
private Professor professor;
....set、get方法
...toString方法
@Override
protected Object clone()throws CloneNotSupportedException{
Student newStudent=(Student) super.clone();
newStudent.professor=(Professor) professor.clone();
return newStudent;
}
}
class Professor implements Cloneable {
private String name;
private int age;
...set、get方法
...toString方法
@Override
protected Object clone()throws CloneNotSupportedException{
return super.clone();
}
}
這一次發現修改s2的引用型別後,並沒有對s1產生影響了。其實深拷貝也就是把所有的引用的物件屬性再做一個clone,直到最終的所有的屬性都是基本資料型別。