浅拷贝

基本概念

如果属性是基本类型,拷贝的就是基本类型的值;如果属性是引用类型,拷贝的就是内存地址 ,因此如果其中一个对象改变了这个地址,就会影响到另一个对象。

代码实现

实现对象拷贝的类,需要实现 Cloneable 接口,并覆写 clone() 方法。

  1. public class Student implements Cloneable {
  2. //引用类型
  3. private Subject subject;
  4. //基础数据类型
  5. private String name;
  6. private int age;
  7. public Subject getSubject() {
  8. return subject;
  9. }
  10. public void setSubject(Subject subject) {
  11. this.subject = subject;
  12. }
  13. public String getName() {
  14. return name;
  15. }
  16. public void setName(String name) {
  17. this.name = name;
  18. }
  19. public int getAge() {
  20. return age;
  21. }
  22. public void setAge(int age) {
  23. this.age = age;
  24. }
  25. /**
  26. * 重写clone()方法
  27. * @return
  28. */
  29. @Override
  30. public Object clone() {
  31. //浅拷贝
  32. try {
  33. // 直接调用父类的clone()方法
  34. return super.clone();
  35. } catch (CloneNotSupportedException e) {
  36. return null;
  37. }
  38. }
  39. @Override
  40. public String toString() {
  41. return "[Student: " + this.hashCode() + ",subject:" + subject +
  42. ",name:" + name + ",age:" + age + "]";
  43. }
  44. }

浅拷贝和对象拷贝的区别

Student studentB = (Student) studentA.clone() 换成了 Student studentB = studentA
对象拷贝后没有生成新的对象,二者的对象地址是一样的;而浅拷贝的对象地址是不一样的。

深拷贝

基本概念

  1. 对于基本数据类型的成员对象,因为基础数据类型是值传递的,所以是直接将属性值赋值给新的对象。基础类型的拷贝,其中一个对象修改该值,不会影响另外一个(和浅拷贝一样)。
  2. 对于引用类型,比如数组或者类对象,深拷贝会新建一个对象空间,然后拷贝里面的内容,所以它们指向了不同的内存空间。改变其中一个,不会对另外一个也产生影响。
  3. 对于有多层对象的,每个对象都需要实现 Cloneable 并重写 clone() 方法,进而实现了对象的串行层层拷贝。

    代码实现

    1. public class Subject implements Cloneable {
    2. private String name;
    3. public Subject(String name) {
    4. this.name = name;
    5. }
    6. public String getName() {
    7. return name;
    8. }
    9. public void setName(String name) {
    10. this.name = name;
    11. }
    12. @Override
    13. protected Object clone() throws CloneNotSupportedException {
    14. //Subject 如果也有引用类型的成员属性,也应该和 Student 类一样实现
    15. return super.clone();
    16. }
    17. @Override
    18. public String toString() {
    19. return "[Subject: " + this.hashCode() + ",name:" + name + "]";
    20. }
    21. }
    1. public class Student implements Cloneable {
    2. //引用类型
    3. private Subject subject;
    4. //基础数据类型
    5. private String name;
    6. private int age;
    7. public Subject getSubject() {
    8. return subject;
    9. }
    10. public void setSubject(Subject subject) {
    11. this.subject = subject;
    12. }
    13. public String getName() {
    14. return name;
    15. }
    16. public void setName(String name) {
    17. this.name = name;
    18. }
    19. public int getAge() {
    20. return age;
    21. }
    22. public void setAge(int age) {
    23. this.age = age;
    24. }
    25. /**
    26. * 重写clone()方法
    27. * @return
    28. */
    29. @Override
    30. public Object clone() {
    31. //深拷贝
    32. try {
    33. // 直接调用父类的clone()方法
    34. Student student = (Student) super.clone();
    35. //调用subject的clone()方法
    36. student.subject = (Subject) subject.clone();
    37. return student;
    38. } catch (CloneNotSupportedException e) {
    39. return null;
    40. }
    41. }
    42. @Override
    43. public String toString() {
    44. return "[Student: " + this.hashCode() + ",subject:" + subject + ",name:" + name + ",age:" + age + "]";
    45. }
    46. }