美文网首页
clone()之浅拷贝与深拷贝

clone()之浅拷贝与深拷贝

作者: BestbpF | 来源:发表于2018-09-19 10:56 被阅读17次

    简述

    我们在Java开发时,有时会涉及到对象拷贝复制,就是将一个对象的所有属性(成员变量)复制到另一个对象中,而拷贝又分为浅拷贝和深拷贝,造成这种分法的主要原因就是【值传递】和【引用传递】的不同

    【浅拷贝】
    • 若成员变量为基本数据类型,拷贝时为【值传递】,是两份不同的数据,改变A类中的该变量,B类不会变化
    • 若成员变量为引用类型,拷贝时为【引用传递】,拷贝的是引用变量,实际上两个引用变量指向的是一个实例对象,若改变A类中的该变量,B会变化,即为【浅拷贝】
    【深拷贝】
    • 深拷贝就是对引用类型的成员变量拷贝时,拷贝整个对象,而不是只拷贝引用

    clone()方法

    • Object提供了clone()方法帮助我们进行拷贝,但它只是浅拷贝,如果需要深拷贝,需要重写clone()方法的逻辑
    • 由源码protected native Object clone() throws CloneNotSupportedException可知,我们无法直接调用clone()方法,我们需要重写该方法并使用super.clone()方法去调用Object的clone方法来实现
    • 使用clone方法的类必须实现Cloneable接口,否则会抛出异常CloneNotSupportedException

    【上代码!!!】

    【浅拷贝】
    public class Teacher {
        
        private String name;
        
        private Subject subject;
    
        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 Object clone() throws CloneNotSupportedException {
            return super.clone();
        }
    
        @Override
        public String toString() {
            return "Teacher [name=" + name + ", subject=" + subject + "]";
        }
    }
    
    public class Subject {
        
        private String name;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        @Override
        public String toString() {
            return "Subject [name=" + name + "]";
        }
    }
    
        public static void main(String[] args) {
            Subject subject = new Subject();
            subject.setName("数学");
            Teacher teacher1 = new Teacher();
            teacher1.setName("张老师");
            teacher1.setSubject(subject);
            
            Teacher teacher2 = null;
            try {
                System.out.println("克隆后------------------");
                teacher2 = (Teacher) teacher1.clone();
                System.out.println("teacher 2:" + teacher2);
                System.out.println("改变teacher1后------------------");
                teacher1.getSubject().setName("语文");
                System.out.println("teacher 2:" + teacher2);
            } catch (CloneNotSupportedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    

    可以发现改变teacher1的subject后,克隆的对象teacher2的subject也发生了变化,这就是【浅拷贝】

    【深拷贝】
    public class Teacher implements Cloneable {
        
        private String name;
        
        private Subject subject;
    
        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 Object clone() throws CloneNotSupportedException {
            Teacher teacher = (Teacher) super.clone();
            Subject subject = (Subject) teacher.getSubject().clone();
            teacher.setSubject(subject);    
            return teacher;
        }
    
        @Override
        public String toString() {
            return "Teacher [name=" + name + ", subject=" + subject + "]";
        }
    }
    
    public class Subject implements Cloneable {
        
        private String name;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        @Override
        public String toString() {
            return "Subject [name=" + name + "]";
        }
        
        @Override
        public Object clone() throws CloneNotSupportedException {
            return super.clone();
        }
    }
    
        public static void main(String[] args) {
            Subject subject = new Subject();
            subject.setName("数学");
            Teacher teacher1 = new Teacher();
            teacher1.setName("张老师");
            teacher1.setSubject(subject);
            
            Teacher teacher2 = null;
            try {
                System.out.println("克隆后------------------");
                teacher2 = (Teacher) teacher1.clone();
                System.out.println("teacher 2:" + teacher2);
                System.out.println("改变teacher1后------------------");
                teacher1.getSubject().setName("语文");
                System.out.println("teacher 2:" + teacher2);
            } catch (CloneNotSupportedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    

    其实就是让subject也实现克隆,然后在teacher的clone方法里,重新setSubject为subject的克隆,就完成了深拷贝

    相关文章

      网友评论

          本文标题:clone()之浅拷贝与深拷贝

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