1005
技術社區[雲棲]
Java中的深克隆和淺克隆——Cloneable接口
一、沒有使用克隆帶來的問題public class CloneTest
{
static Student s = new Student("aaa", 20);
// 直接賦值帶來的問題
public static void noclone()
{
// 傳的是引用的副本,改變了noCloneStudent也改變了s
Student noCloneStudent = new Student();
noCloneStudent = s;
noCloneStudent.setName("bbb");
noCloneStudent.setAge(21);
System.out.println(s);
System.out.print(noCloneStudent);
}
}
Student [name=bbb, age=21]
Student [name=bbb, age=21]
本意是設置noCloneStudent中的值,但把原來的對象s中的值也改變了。
二、淺克隆與深克隆
①淺克隆——若要克隆Student對象,隻克隆他自身以及他包含的所有對象的引用地址。
②深克隆——克隆除自身以外所有的對象,包括自身所包含的所有對象實例。由具體的需求決定深克隆的層次(N層克隆)。
三、淺克隆
public class Student implements Cloneable
{
private String name;
private int age;
public Student()
{
super();
}
public Student(String name, int age)
{
super();
this.name = name;
this.age = age;
}
// 淺克隆
protected Object clone() throws CloneNotSupportedException
{
return super.clone();
}
public String toString()
{
return "Student [name=" + name + ", age=" + age + "]";
}
......
}
public class CloneTest
{
static Student s = new Student("aaa", 20);
// 淺克隆
public static void test0() throws Exception
{
Student ss = (Student) s.clone();
ss.setName("bbb");
ss.setAge(21);
System.out.println(s);
System.out.print(ss);
}
}
Student [name=aaa, age=20]
Student [name=bbb, age=21]
克隆的效果就達到了。
四、深克隆
public class TClass implements Cloneable
{
private Student stu;
private String name;
private List<String> courses = new ArrayList<String>();
public TClass()
{
super();
}
public TClass(Student stu, String name, List<String> courses)
{
super();
this.stu = stu;
this.name = name;
this.courses = courses;
}
// 深克隆
public Object clone() throws CloneNotSupportedException
{
TClass tea = (TClass) super.clone();
tea.stu = (Student) tea.stu.clone();
return tea;
}
public String toString()
{
return "TClass [stu=" + stu + ", name=" + name + ", courses=" + courses + "]";
}
......
}
// 深克隆
public static void test1() throws Exception
{
TClass t = new TClass();
t.setStu(s);
t.setName("張老師");
t.getCourses().add("JAVA");
t.getCourses().add("C#");
System.out.println(t);
TClass tt = (TClass) t.clone();
Student sss = (Student) s.clone();
sss.setName("bbb");
sss.setAge(21);
tt.setStu(sss);
tt.setName("李老師");
tt.getCourses().add("oracle");
tt.getCourses().add("mysql");
System.out.println(t);
System.out.println(tt);
}
TClass [stu=Student [name=aaa, age=20], name=張老師, courses=[JAVA, C#]]
TClass [stu=Student [name=aaa, age=20], name=張老師, courses=[JAVA, C#, oracle, mysql]]
TClass [stu=Student [name=bbb, age=21], name=李老師, courses=[JAVA, C#, oracle, mysql]]
動態數組還是保留了原來的引用,所以其數組沒有達到拷貝的效果。
改造一下,讓其中的數組有新的引用
public class TClass implements Cloneable
{
private Student stu;
private String name;
private List<String> courses = new ArrayList<String>();
public TClass()
{
super();
}
public TClass(Student stu, String name, List<String> courses)
{
super();
this.stu = stu;
this.name = name;
this.courses = courses;
}
// 深克隆(更深一層)
public Object clone() throws CloneNotSupportedException
{
TClass tea = (TClass) super.clone();
tea.stu = (Student) tea.stu.clone();
tea.courses = new ArrayList<String>(); // 指向不同引用
return tea;
}
public String toString()
{
return "TClass [stu=" + stu + ", name=" + name + ", courses=" + courses + "]";
}
......
}
TClass[stu=Student [name=aaa, age=20], name=張老師, courses=[Java, C#]]
TClass[stu=Student [name=bbb, age=21], name=李老師, courses=[oracle, mysql]]
再改造一下,希望動態數組既有了新的引用,又保留了原值
public class TClass3 implements Cloneable
{
private Student stu;
private String name;
private List<String> courses = new ArrayList<String>();
public TClass()
{
super();
}
public TClass(Student stu, String name, List<String> courses)
{
super();
this.stu = stu;
this.name = name;
this.courses = courses;
}
// 深克隆(更深一層)
public Object clone() throws CloneNotSupportedException
{
TClass tea = (TClass) super.clone();
tea.stu = (Student) tea.stu.clone();
// 指向不同引用
tea.courses = new ArrayList<String>();
// 又想保留原有的值
for (int i = 0; i < courses.size(); i++)
{
tea.courses.add(courses.get(i));
}
return tea;
}
public String toString()
{
return "TClass [stu=" + stu + ", name=" + name + ", courses=" + courses + "]";
}
......
}
Teacher [stu=Student [name=aaa, age=20], name=張老師, courses=[Java, C#]]
Teacher [stu=Student [name=bbb, age=21], name=李老師, courses=[Java, C#, oracle, spring]]
最後更新:2017-04-04 07:33:15