共计 3159 个字符,预计需要花费 8 分钟才能阅读完成。
为什么使用 clone
存在一个对象 A,A 已有初始值,这时候可能需要一个新的对象 B 和 A 相同,但是 A 和 B 是两个独立的对象,任意一个改动都不影响其中一个的值,但是 B 的初始值由 A 确定,这时候 clone 就是最有效也是最简单的方法。
new 一个对象和 clone 一个对象的区别
- new 操作符的本意是分配内存空间,java 程序执行到 new 操作符时,首先去看 new 操作符后面的类型,知道类型才能知道需要分配多大的内存空间,分配完成,调用构造函数,填充对象,完成对象的初始化。
- clone 的第一步也是分配内存,java 程序执行到 clone 这一步时,分配的内存和调用 clone 方法的对象相同,在根据原对象完成对新对象的初始化,一个新的对象就被创建完成。
复制对象和克隆对象
需要克隆的对象要继承 Cloneable 接口,并重写 clone() 方法
复制对象
定义类:
public class People1 { | |
private String name; | |
private Integer age; | |
public People1(String name, Integer age) { | |
this.name = name; | |
this.age = age; | |
} | |
} |
复制测试
public class test {public static void main(String[] args) {People1 people1 = new People1("people",18); | |
People1 people11 = people1; | |
System.out.println(people1); | |
System.out.println(people11); | |
System.out.println(people1 == people11); | |
} | |
} |
结果:
证明复制对象只是指向原来的对象,people1 和 people11 只是引用同一个对象
clone 对象
定义类:
public class People2 implements Cloneable{ | |
private String name; | |
private Integer age; | |
public People2(String name, Integer age) { | |
this.name = name; | |
this.age = age; | |
} | |
public String getName() {return name;} | |
public Integer getAge() {return age;} | |
public void setName(String name) {this.name = name;} | |
public void setAge(Integer age) {this.age = age;} | |
@Override | |
protected Object clone() throws CloneNotSupportedException {return super.clone(); | |
} | |
} |
测试:
public class test {public static void main(String[] args) { | |
//clone | |
People2 people2 = new People2("people",18); | |
People2 people22 = null; | |
try {people22 = (People2) people2.clone();} catch (CloneNotSupportedException e) {e.printStackTrace(); | |
} | |
System.out.println(people2); | |
System.out.println(people22); | |
System.out.println(people2 == people22); | |
} | |
} |
结果:
可以看出 people2 和 people22 指向的对象并不是同一个的
浅克隆与深克隆
定义类:
Student 类:
public class Student implements Cloneable{ | |
private String name; | |
private Integer age; | |
private Teacher teacher; | |
public Student(String name, Integer age,Teacher teacher) { | |
this.name = name; | |
this.age = age; | |
this.teacher = teacher; | |
} | |
public String getName() {return name;} | |
public void setName(String name) {this.name = name;} | |
public Integer getAge() {return age;} | |
public void setAge(Integer age) {this.age = age;} | |
public Teacher getTeacher() {return teacher;} | |
public void setTeacher(Teacher teacher) {this.teacher = teacher;} | |
@Override | |
public String toString() {return "学生:name=" + name + ", age=" + age + ", 指导" + teacher;} | |
@Override | |
protected Object clone() throws CloneNotSupportedException {return super.clone(); | |
} | |
} |
Teacher 类
public class Teacher { | |
private String name; | |
private Integer age; | |
public Teacher(String name, Integer age) { | |
this.name = name; | |
this.age = age; | |
} | |
public String getName() {return name;} | |
public void setName(String name) {this.name = name;} | |
public Integer getAge() {return age;} | |
public void setAge(Integer age) {this.age = age;} | |
@Override | |
public String toString() {return "老师:name=" + name + ", age=" + age ;} | |
} |
浅克隆
main 函数
public class test2 {public static void main(String[] args) {Teacher teacher = new Teacher("刘老师",18); | |
Student student1 = new Student("小明",10,teacher); | |
Student student2 = null; | |
try {student2 = (Student) student1.clone();} catch (CloneNotSupportedException e) {e.printStackTrace(); | |
} | |
Teacher t1 = student2.getTeacher(); | |
t1.setName("张老师"); | |
t1.setAge(30); | |
student2.setName("小红"); | |
student2.setAge(9); | |
student2.setTeacher(t1); | |
System.out.println(student1); | |
System.out.println(student2); | |
} | |
} |
结果:
修改 student2 中的 Teacher 类,student1 也跟着改变,而修改姓名和年龄并不会修改,由此得出才重新 clone 方法时不能直接 super
深克隆
- Teacher 继承 Cloneable
- Student 重写 clone 方法
Student newStudent = (Student) super.clone(); | |
newStudent.teacher = (Teacher) teacher.clone(); | |
return newStudent; |
运行上方测试代码,结果:
完成预想结果
正文完
发表至: java
2019-07-18