本文共 6221 字,大约阅读时间需要 20 分钟。
开发过程中,我们会遇到把现有的一个对象的所有成员拷贝给另一个对象的需求,会出现在组合、包含等关系中,比如学生和课程的关系
java存在基本数据类型和引用数据类型,在赋值操作、用作方法参数或返回值时,会有值传递和引用地址传递的差别。课程类
/** * 课程类 * * @author wangkai * @created 2020/3/19 */public class Subject { private String name; public Subject(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Subject{" + this.hashCode() + ",name='" + name + '\'' + '}'; }}
学生类
/** * 学生类 * * @author wangkai * @created 2020/3/19 */public class Student implements Cloneable { private Integer age; private String name; private Subject subject; public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Subject getSubject() { return subject; } public void setSubject(Subject subject) { this.subject = subject; } @Override public String toString() { return "Student{" + this.hashCode() + ",age=" + age + ", name='" + name + '\'' + ", subject=" + subject + '}'; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); }}
测试类
/** * 浅拷贝 * * @author wangkai * @created 2020/3/19 */public class ShallowAndDeepCopy { public static void main(String[] args) throws CloneNotSupportedException { //初始化课程为语文课 Subject subject = new Subject("Chinese"); //学生1选课 Student student1 = new Student(); student1.setAge(20); student1.setName("WangKai"); student1.setSubject(subject); Student student2 = (Student) student1.clone(); //对象拷贝 Student student2 = student1; student2.setAge(30); student2.setName("XiaoMing"); //学生2学习了历史课 Subject subject2 = student2.getSubject(); subject2.setName("history"); System.out.println("Student1:" + student1.toString()); System.out.println("Student2:" + student2.toString()); }}
运行结果:
Student1:Student{ 1639705018,age=20, name='WangKai', subject=Subject{ 1627674070,name='history'}}Student2:Student{ 1360875712,age=30, name='XiaoMing', subject=Subject{ 1627674070,name='history'}}Process finished with exit code 0
根据运行结果,可知student1.clone()克隆之后生成了新的对象student2,基础数据类型的修改互相不影响,引用数据类型的修改会有影响,两个对象生成的Subject引用类型指向的是同一个地址
引申:浅拷贝和对象拷贝的区别
将Student student2 = (Student) student1.clone()改为Student student2 = student1就成了对象拷贝输出结果
Student1:Student{ 1639705018,age=30, name='XiaoMing', subject=Subject{ 1627674070,name='history'}}Student2:Student{ 1639705018,age=30, name='XiaoMing', subject=Subject{ 1627674070,name='history'}}Process finished with exit code 0
通过查看hashcode发现,对象拷贝没有生成新的Student对象,二者对象地址是一致的,而浅拷贝地址是不一样的
由于浅拷贝存在的问题,我们引出深拷贝
课程类:
/** * 课程类 * 改造点:实现Cloneable,重新方法 * * @author wangkai * @created 2020/3/19 */public class Subject implements Cloneable { private String name; public Subject(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Subject{" + this.hashCode() + ",name='" + name + '\'' + '}'; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); }}
学生类:
/** * 学生类 * 改动点:重新clone方法,对引用类型变量重新克隆赋值 * @author wangkai * @created 2020/3/19 */public class Student implements Cloneable { private Integer age; private String name; private Subject subject; public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Subject getSubject() { return subject; } public void setSubject(Subject subject) { this.subject = subject; } @Override public String toString() { return "Student{" + this.hashCode() + ",age=" + age + ", name='" + name + '\'' + ", subject=" + subject + '}'; } @Override protected Object clone() throws CloneNotSupportedException { Student student = (Student) super.clone(); student.subject = (Subject) subject.clone(); return student; }}
测试类
/** * 深拷贝:main方法与浅拷贝一致,改的是对象内部实现 * * @author wangkai * @created 2020/3/19 */public class ShallowAndDeepCopy { public static void main(String[] args) throws CloneNotSupportedException { //初始化课程为语文课 Subject subject = new Subject("Chinese"); //学生1选课 Student student1 = new Student(); student1.setAge(20); student1.setName("WangKai"); student1.setSubject(subject); Student student2 = (Student) student1.clone(); //Student student2=student1; student2.setAge(30); student2.setName("XiaoMing"); //学生2学习了历史课 Subject subject2 = student2.getSubject(); subject2.setName("history"); System.out.println("Student1:" + student1.toString()); System.out.println("Student2:" + student2.toString()); }}
运行结果如下:
Student1:Student{ 1639705018,age=20, name='WangKai', subject=Subject{ 1627674070,name='Chinese'}}Student2:Student{ 1360875712,age=30, name='XiaoMing', subject=Subject{ 1625635731,name='history'}}Process finished with exit code 0
由输出结果可知:深拷贝之后,其中一个对象的数据类型和引用类型的修改都不会影响另外一个对象
注意:
转载地址:http://eobjn.baihongyu.com/