美文网首页
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的克隆,就完成了深拷贝

相关文章

  • 面试:Object 方法与原理

    Object 方法与原理 1. clone 方法 clone 方法的用法是对象的浅拷贝和深拷贝,clone是浅拷贝...

  • 五、面试总结(五)

    对象 拷贝(clone) 如何实现对象克隆 深拷贝和浅拷贝区别 深拷贝和浅拷贝如何实现激活机制 写clone()方...

  • Cloneable 接口

    浅拷贝(shallow clone)和深拷贝(deep clone) 浅拷贝是指拷贝对象时仅仅拷贝对象本身和对象中...

  • clone()之浅拷贝与深拷贝

    简述 我们在Java开发时,有时会涉及到对象拷贝复制,就是将一个对象的所有属性(成员变量)复制到另一个对象中,而拷...

  • Objective-C中的浅拷贝和深拷贝

    Objective-C中的浅拷贝和深拷贝IOS开发之深拷贝与浅拷贝(mutableCopy与Copy)详解iOS ...

  • 原型模式

    简介 实现Cloneable接口,重写clone方法。要注意深拷贝和浅拷贝问题。 浅拷贝:新实例的...

  • JS中的深拷贝与浅拷贝

    知乎:js中的深拷贝和浅拷贝? 掘金: js 深拷贝 vs 浅拷贝 前言 首先深拷贝与浅拷贝只针对 Object,...

  • 深入理解 JavaScript 对象和数组拷贝

    前言 本文要解决的问题: 为什么会有深拷贝(deep clone)和浅拷贝(shallow clone)的存在 理...

  • 深拷贝、浅拷贝---C#

    关于Clone一般区分为两种,浅拷贝和深拷贝。 浅拷贝 ​ 指的是拷贝一个对象的时候,只拷贝对对象的引用。当你...

  • 认识js下的浅拷贝与深拷贝

    浅拷贝与深拷贝 首先深拷贝和浅拷贝只针对像 Object, Array 这样的复杂对象的。简单来说,浅拷贝只拷贝一...

网友评论

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

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