美文网首页
什么是浅拷贝和深拷贝?

什么是浅拷贝和深拷贝?

作者: 分布式与微服务 | 来源:发表于2022-08-05 09:02 被阅读0次

创建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

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

什么是浅拷贝?

我稍等改动下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对象。

像上面这种情况,当拷贝时,只拷贝了部分属性,没有拷贝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='罗翔老师'}

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

总结

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

相关文章

  • iOS--拷贝相关题

    1、什么是深拷贝什么是浅拷贝?浅拷贝和深拷贝的区别 * 浅拷贝(shallow copy):指针拷贝,对于被拷贝对...

  • js浅拷贝、深拷贝

    前言 本文主要简单讲一下什么是浅拷贝、什么是深拷贝、深拷贝与浅拷贝的区别,以及怎么进行深拷贝和怎么进行浅拷贝。 一...

  • iOS深拷贝(MutableCopy)与浅拷贝(Copy)的区别

    深拷贝和浅拷贝的概念 iOS中有深拷贝和浅拷贝的概念,那么何为深拷贝何为浅拷贝呢?浅拷贝:浅拷贝并不拷贝对象本身,...

  • Java基础 - 深拷贝和浅拷贝

    Java 的深拷贝和浅拷贝 什么是深拷贝、浅拷贝 (深克隆、浅克隆)? 在 Java 中,数据类型分为 基本数据类...

  • 深拷贝、浅拷贝的理解与使用场景

    什么是深拷贝、浅拷贝? 通俗解释:深拷贝是内容拷贝,浅拷贝是地址拷贝 区别点: 深拷贝会创建一个新的内存空间,拷贝...

  • 深拷贝和浅拷贝

    1.深拷贝:地址的拷贝 2.浅拷贝:是值得拷贝 深拷贝和浅拷贝的区别 A拷贝B B变A变是浅拷贝 A拷贝B B变A...

  • Object 对象

    什么是浅拷贝,如何实现浅拷贝?什么是深拷贝,如何实现深拷贝? 是什么: 浅拷贝: 将原对象或原数组的引用直接赋给新...

  • iOS面试题-第二页

    11.深拷贝和浅拷贝的理解. 深拷贝;拷贝的内容. 浅拷贝:拷贝的指针. 深拷贝如: NSMutableDicti...

  • python切片是引用还是复制

    切片是深拷贝 等号是引用,不是拷贝 深拷贝、浅拷贝都属于拷贝,改变原始列表拷贝列表通常不变,为什么说深、浅呢?是指...

  • iOS - copy 与 mutableCopy

    一说到拷贝,就不得不提浅拷贝和深拷贝。 何谓浅拷贝?何谓深拷贝? 往简单的说: 浅拷贝:拷贝地址。 深拷贝:拷贝内...

网友评论

      本文标题:什么是浅拷贝和深拷贝?

      本文链接:https://www.haomeiwen.com/subject/quwrirtx.html