创建java对象的方式包括new、反射、反序列化、拷贝,那么什么是拷贝呢?浅拷贝和深拷贝又有什么区别呢?

什么是拷贝

拷贝就是为了复用原对象的部分或全部数据,在原对象的基础上通过复制的方式创建一个新的对象。

Object类中有native类型的clone方法

protected native Object clone() throws CloneNotSupportedException; 复制代码

如果一个对象可以被拷贝,那么该对象对应的类需要实现Cloneable接口,并重写Object的clone方法。

必须实现Cloneable接口,否则调用clone方法会抛出java.lang.CloneNotSupportedExecption异常

//Cloneable接口中没有任何参数或抽象方法,该接口只是一个标识 public interface Cloneable { } 复制代码

//如Student类,实现Cloneable接口,重写Object的clone方法 public class Student implements Cloneable{ private String sname; private Integer sage; ... @Override protected Student clone() throws CloneNotSupportedException { return (Student) super.clone(); } } 复制代码

举个栗子

public class cloneObject { public static void main(String[] args) throws CloneNotSupportedException { Student student = new Student("学生1",18); System.out.println("clone前的Student对象为:" student); Student cloneStudent = student.clone(); System.out.println("clone后的Student对象为:" cloneStudent); System.out.println("Student对象与cloneStudent对象是否相等:" student.equals(cloneStudent)); } } 复制代码

打印结果为

clone前的Student对象为:Student{sname='学生1', sage=18} clone后的Student对象为:Student{sname='学生1', sage=18} Student对象与cloneStudent对象是否相等:false 复制代码

简述什么是深拷贝和浅拷贝(简单认清深拷贝和浅拷贝)(1)

由此可见,拷贝是创建了一个新的对象。

什么是浅拷贝?

我稍等改动下Student类来举例说明

Student类中除了String类型和Integer类型的属性外,添加了一个Teacher类型的属性,Teacher类中只有一个String类型的tname属性

public class Student implements Cloneable{ private String sname; private Integer sage; private Teacher teacher; ... @Override protected Student clone() throws CloneNotSupportedException { return (Student) super.clone(); } 复制代码

public class Teacher { private String tname; 复制代码

再次调用sutdent对象的clone方法

public static void main(String[] args) throws CloneNotSupportedException { Teacher teacher = new Teacher("罗翔老师"); Student student = new Student("学生1",18,teacher); System.out.println("clone前的Student对象为:" student); Student cloneStudent = student.clone(); System.out.println("clone后的Student对象为:" cloneStudent); System.out.println("Student对象与cloneStudent对象是否相等:" student.equals(cloneStudent)); System.out.println("student对象和cloneStudent对象中的teacher属性是否相等:" student.getTeacher().equals(cloneStudent.getTeacher())); } 复制代码

两个sutdent对象比较结果在意料之中,为false。但是两种student对象中的teacher属性比较结果却是true。

clone前的Student对象为:Student{sname='学生1', sage=18, teacher=com.hard.qz.clone.Teacher@1b6d3586} clone后的Student对象为:Student{sname='学生1', sage=18, teacher=com.hard.qz.clone.Teacher@1b6d3586} Student对象与cloneStudent对象是否相等:false student对象和cloneStudent对象中的teacher属性是否相等:true 复制代码

//修改student对象中teacher属性的值,观察cloneStudent对象中的teacher属性的值是否会变 student.getTeacher().setTname("张三老师"); System.out.println("cloneStudent对象中teacher属性的值为:" cloneStudent.getTeacher()); 复制代码

结果为:

cloneStudent对象中teacher属性的值为:Teacher{tname='张三老师'} 复制代码

当修改student对象中teacher属性的值时,会影响到cloneStudent对象中teacher属性的值 由此说明:两个student对象共用一个teacher对象。

简述什么是深拷贝和浅拷贝(简单认清深拷贝和浅拷贝)(2)

像上面这种情况,当拷贝时,只拷贝了部分属性,没有拷贝Object和数组属性时,这种拷贝被称为浅拷贝。

什么是深拷贝?

当拷贝时,拷贝了一个对象中的所有属性,包括Object和数组属性,这种拷贝被称为深拷贝

如何实现深拷贝?

重写clone方法时,对Object和数组属性也调用clone方法就可以实现深拷贝,要求被拷贝对象的Object属性也实现Cloneable接口,重写了clone方法。

//Teacher类实现了Cloneable接口,重写了clone方法 public class Teacher implements Cloneable{ private String tname; @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } } //Student类重写clone方法时,调用了Teacher类的clone方法,实现深拷贝 @Override protected Student clone() throws CloneNotSupportedException { Student cloneStudent = (Student) super.clone(); cloneStudent.setTeacher((Teacher) cloneStudent.getTeacher().clone()); return cloneStudent; } 复制代码

对student对象拷贝并比较两个对象及对象中的属性是否相等。

public class cloneObject { public static void main(String[] args) throws CloneNotSupportedException { Teacher teacher = new Teacher("罗翔老师"); Student student = new Student("学生1",18,teacher); System.out.println("clone前的Student对象为:" student); Student cloneStudent = student.clone(); System.out.println("clone后的Student对象为:" cloneStudent); System.out.println("Student对象与cloneStudent对象是否相等:" student.equals(cloneStudent)); System.out.println("student对象和cloneStudent对象中的teacher属性是否相等:" student.getTeacher().equals(cloneStudent.getTeacher())); //修改student对象中teacher属性的值,观察cloneStudent对象中的teacher属性的值是否会变 student.getTeacher().setTname("张三老师"); System.out.println("cloneStudent对象中teacher属性的值为:" cloneStudent.getTeacher()); } } 复制代码

打印结果为

clone前的Student对象为:Student{sname='学生1', sage=18, teacher=Teacher{tname='罗翔老师'}} clone后的Student对象为:Student{sname='学生1', sage=18, teacher=Teacher{tname='罗翔老师'}} Student对象与cloneStudent对象是否相等:false student对象和cloneStudent对象中的teacher属性是否相等:false cloneStudent对象中teacher属性的值为:Teacher{tname='罗翔老师'} 复制代码

打印结果显示深拷贝后的两个对象及其中的属性都不相等。

简述什么是深拷贝和浅拷贝(简单认清深拷贝和浅拷贝)(3)

总结
  1. 拷贝是为了部分或全部复用原对象的属性,在原对象的基础上创建一个新的对象。
  2. 浅拷贝是拷贝后两个对象地址不相等,但两个对象的部分属性地址相等,新对象并没有拷贝所有的属性,而是复用原对象中的值。
  3. 深拷贝是拷贝后两个对象不仅地址不相等,两个对象的所有属性地址都不相等。

原链接:https://juejin.cn/post/7120876548088922143

,