美文网首页
Java深拷贝和浅拷贝

Java深拷贝和浅拷贝

作者: 二狗不是狗 | 来源:发表于2020-06-29 21:19 被阅读0次

    一.等于实现变量赋值

    通过等于号实现变量赋值,实际上是把copy变量也指向原来的对象,并没有创建任何新的对象和属性;例如下面的例子我们打印可以看到原来student的hashCode和copy变量的hashCode一致。


    image.png
    @Data
    public class Subject {
    
        private int subjectId;
    
        private String subjectNumber;
    
        private StringBuilder subjectName;
    }
    
    @Data
    public class Student {
    
        private int id;
    
        private String number;
    
        private StringBuilder name;
    
        private Subject subject;
    }
    
    public static void main(String[] args) {
        Subject subject = new Subject();
        subject.setSubjectId(1);
        subject.setSubjectNumber("aaa");
        subject.setSubjectName(new StringBuilder("aaa"));
    
        Student student = new Student();
        student.setId(1);
        student.setNumber("aaa");
        student.setName(new StringBuilder("aaa"));
        student.setSubject(subject);
    
        Student copy = student;
    
        copy.setId(2);
        copy.setNumber("aaabbb");
        copy.getName().append("bbb");
    
        copy.getSubject().setSubjectId(2);
        copy.getSubject().setSubjectNumber("aaabbb");
        copy.getSubject().getSubjectName().append("bbb");
    
        logger.info("student = {}", student.hashCode());
        logger.info("copy = {}", copy.hashCode());
    
        logger.info("subject = {}", JSON.toJSONString(subject));
        logger.info("student = {}", JSON.toJSONString(student));
    }
    

    打印结果为:
    student = -859332970
    copy = -859332970
    subject = {"subjectId":2,"subjectName":"aaabbb","subjectNumber":"aaabbb"}
    student = {"id":2,"name":"aaabbb","number":"aaabbb","subject":{"subjectId":2,"subjectName":"aaabbb","subjectNumber":"aaabbb"}}

    二.浅拷贝(复制)

    1. 浅拷贝是按位拷贝对象它会创建一个新对象,例如下面的例子我们打印可以看到原来student的hashCode和copy变量的hashCode不一致。
    2. 如果属性是基本类型,拷贝的就是基本类型的值
    3. 如果属性是内存地址(引用类型),拷贝的就是内存地址
    4. 默认拷贝构造函数只是对对象进行浅拷贝复制,即只复制对象空间而不复制资源。
    image.png
    @Data
    public class Subject {
    
        private int subjectId;
    
        private String subjectNumber;
    
        private StringBuilder subjectName;
    }
    
    @Data
    public class Student implements Cloneable {
    
        private int id;
    
        private String number;
    
        private StringBuilder name;
    
        private Subject subject;
    
        @Override
        public Object clone() {
            try {
                Student student = (Student) super.clone();
                return student;
            } catch (CloneNotSupportedException e) {
                return null;
            }
        }
    }
    
    public static void main(String[] args) {
        Subject subject = new Subject();
        subject.setSubjectId(1);
        subject.setSubjectNumber("aaa");
        subject.setSubjectName(new StringBuilder("aaa"));
    
        Student student = new Student();
        student.setId(1);
        student.setNumber("aaa");
        student.setName(new StringBuilder("aaa"));
        student.setSubject(subject);
    
        Student copy = (Student) student.clone();
    
        copy.setId(2);
        copy.setNumber("aaabbb");
        copy.getName().append("bbb");
    
        copy.getSubject().setSubjectId(2);
        copy.getSubject().setSubjectNumber("aaabbb");
        copy.getSubject().getSubjectName().append("bbb");
    
        logger.info("student = {}", student.hashCode());
        logger.info("copy = {}", copy.hashCode());
    
        logger.info("subject = {}", JSON.toJSONString(subject));
        logger.info("student = {}", JSON.toJSONString(student));
    }
    

    打印结果为:
    student = 96321
    copy = -1425371071
    subject = {"subjectId":2,"subjectName":"aaabbb","subjectNumber":"aaabbb"}
    student = {"id":1,"name":"aaabbb","number":"aaa","subject":{"subjectId":2,"subjectName":"aaabbb","subjectNumber":"aaabbb"}}

    三.深拷贝(复制)

    1. 对于基本数据类型的成员对象,因为基础数据类型是值传递的,所以是直接将属性值赋值给新的对象。基础类型的拷贝,其中一个对象修改该值,不会影响另外一个(和浅拷贝一样)。
    2. 对于引用类型,比如数组或者类对象,深拷贝会新建一个对象空间,然后拷贝里面的内容,所以它们指向了不同的内存空间。改变其中一个,不会对另外一个也产生影响。
    3. 对于有多层对象的,每个对象都需要实现 Cloneable 并重写 clone() 方法,进而实现了对象的串行层层拷贝。
    4. 深拷贝相比于浅拷贝速度较慢并且花销较大。
    5. 下面的例子因为String类和StringBuilder类没有实现Cloneable接口,所以是浅拷贝
    image.png
    @Data
    public class Subject implements Cloneable {
    
        private int subjectId;
    
        private String subjectNumber;
    
        private StringBuilder subjectName;
    
        @Override
        public Object clone() {
            try {
                Subject subject = (Subject) super.clone();
                return subject;
            } catch (CloneNotSupportedException e) {
                return null;
            }
        }
    }
    
    @Data
    public class Student implements Cloneable {
    
        private int id;
    
        private String number;
    
        private StringBuilder name;
    
        private Subject subject;
    
        @Override
        public Object clone() {
            try {
                Student student = (Student) super.clone();
                student.setSubject((Subject) subject.clone());
                return student;
            } catch (CloneNotSupportedException e) {
                return null;
            }
        }
    }
    
    public static void main(String[] args) {
        Subject subject = new Subject();
        subject.setSubjectId(1);
        subject.setSubjectNumber("aaa");
        subject.setSubjectName(new StringBuilder("aaa"));
    
        Student student = new Student();
        student.setId(1);
        student.setNumber("aaa");
        student.setName(new StringBuilder("aaa"));
        student.setSubject(subject);
    
        Student copy = (Student) student.clone();
    
        copy.setId(2);
        copy.setNumber("aaabbb");
        copy.getName().append("bbb");
    
        copy.getSubject().setSubjectId(2);
        copy.getSubject().setSubjectNumber("aaabbb");
        copy.getSubject().getSubjectName().append("bbb");
    
        logger.info("student = {}", student.hashCode());
        logger.info("copy = {}", copy.hashCode());
    
        logger.info("subject = {}", JSON.toJSONString(subject));
        logger.info("student = {}", JSON.toJSONString(student));
    }
    

    打印结果为:
    student = 96321
    copy = -1425371071
    subject = {"subjectId":1,"subjectName":"aaabbb","subjectNumber":"aaa"}
    student = {"id":1,"name":"aaabbb","number":"aaa","subject":{"subjectId":1,"subjectName":"aaabbb","subjectNumber":"aaa"}}

    相关文章

      网友评论

          本文标题:Java深拷贝和浅拷贝

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