目录

  • 什么是对象拷贝
  • 本文描述对象拷贝分类
  • 浅拷贝
  • 实现说明
  • 代码实现
  • 深拷贝
  • 实现说明
  • 代码实现
  • 相同点
  • 区别


什么是对象拷贝

对象拷贝即将源对象复制出一个新的对象,分配新的内存。

本文描述对象拷贝分类

分为浅拷贝和深拷贝

浅拷贝

顾名思义,简单浅层拷贝,将对象所有变量的值复制一份到新对象中。在Java中有基本数据类型引用类型(值存放的是内存地址),而浅拷贝在处理引用对象和基本数据类型一样复制值到新对象,导致新对象的引用变量值是源对象引用变量的内存地址,也就是新对象和就对象操作引用变量是同一个。潜在相互影响隐患。

实现说明

该拷贝必须实现Cloneable接口复写Object的clone方法
若不实现Cloneable接口会报ava.lang.CloneNotSupportedException:异常,应该是一种标准,目前暂未找到合理解释

代码实现

// 引用lombok,少写get/set,toString
import lombok.Data;

@Data
public class ShallowCopyTest implements Cloneable {

    private String name;
    private Integer age;

    private ReferenceObj referenceObj;


    @Override
    protected Object clone() {
        try {
            return super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }

    }

    public static void main(String[] args) {
        ShallowCopyTest shallowCopy1 = new ShallowCopyTest();
        shallowCopy1.setAge(1);
        shallowCopy1.setName("NaiNiu");
        ReferenceObj referenceObj = new ReferenceObj();
        referenceObj.setDesc("奶牛");
        referenceObj.setStatus(1);
        shallowCopy1.setReferenceObj(referenceObj);
        //shallowCopy1:[ShallowCopyTest(name=NaiNiu, age=1, referenceObj=ShallowCopyTest.ReferenceObj(desc=奶牛, status=1))]
        System.out.println("shallowCopy1:[" + shallowCopy1.toString() + "]");
        ShallowCopyTest shallowCopy2 = (ShallowCopyTest) shallowCopy1.clone();
        shallowCopy2.setName("LiMao");
        shallowCopy2.setAge(2);
        ReferenceObj referenceObj2 = shallowCopy2.getReferenceObj();
        //修改引用变量内容
        referenceObj2.setDesc("狸猫");
        referenceObj2.setStatus(2);

        //shallowCopy1:[ShallowCopyTest(name=NaiNiu, age=1, referenceObj=ShallowCopyTest.ReferenceObj(desc=狸猫, status=2))]
        //shallowCopy2:[ShallowCopyTest(name=LiMao, age=2, referenceObj=ShallowCopyTest.ReferenceObj(desc=狸猫, status=2))]
        System.out.println("shallowCopy1:[" + shallowCopy1.toString() + "]");
        System.out.println("shallowCopy2:[" + shallowCopy2.toString() + "]");
    }

    @Data
    public static class ReferenceObj implements Cloneable {
        private String desc;
        private Integer status;

        @Override
        protected Object clone() throws CloneNotSupportedException {
            return super.clone();
        }
    }
}

深拷贝

顾名思义,简单浅层拷贝更深层次拷贝,即将对象所有变量的值复制一份到新对象中,并对引用变量进行深拷贝,依次深拷贝直到拷贝完成。

实现说明

该拷贝也必须实现Cloneable接口和复写Object的clone方法,引用对象变量也要实现Cloneable接口和复写Object的clone方法才能完成深拷贝,遇到引用变量需要循环拷贝直到拷贝完成
若不实现Cloneable接口也会报ava.lang.CloneNotSupportedException:异常

代码实现

// 引用lombok,少写get/set,toString
import lombok.Data;

@Data
public class DeepCopyTest implements Cloneable {

    private String name;
    private Integer age;

    private ReferenceObj referenceObj;

    @Override
    protected Object clone() {
        try {
        	//源对象拷贝
            DeepCopyTest clone = (DeepCopyTest) super.clone();
            //将引用变量进行拷贝,若内部还有引用变量需要循环拷贝直到没有,才算完成
            ReferenceObj referenceObj = (ReferenceObj) this.getReferenceObj().clone();
            // 赋值给新对象
            clone.setReferenceObj(referenceObj);
            return clone;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }


    }

    public static void main(String[] args) {
        DeepCopyTest deepCopy1 = new DeepCopyTest();
        deepCopy1.setAge(1);
        deepCopy1.setName("NaiNiu");
        ReferenceObj referenceObj = new ReferenceObj();
        referenceObj.setDesc("奶牛");
        referenceObj.setStatus(1);
        deepCopy1.setReferenceObj(referenceObj);
        //deepCopy1:[DeepCopyTest(name=NaiNiu, age=1, referenceObj=DeepCopyTest.ReferenceObj(desc=奶牛, status=1))]
        System.out.println("deepCopy1:[" + deepCopy1.toString() + "]");
        DeepCopyTest deepCopy2 = (DeepCopyTest) deepCopy1.clone();
        deepCopy2.setName("LiMao");
        deepCopy2.setAge(2);
        ReferenceObj referenceObj2 = deepCopy2.getReferenceObj();
        //修改引用变量内容
        referenceObj2.setDesc("狸猫");
        referenceObj2.setStatus(2);

        //deepCopy1:[DeepCopyTest(name=NaiNiu, age=1, referenceObj=DeepCopyTest.ReferenceObj(desc=奶牛, status=1))]
        //deepCopy2:[DeepCopyTest(name=LiMao, age=2, referenceObj=DeepCopyTest.ReferenceObj(desc=狸猫, status=2))]
        System.out.println("deepCopy1:[" + deepCopy1.toString() + "]");
        System.out.println("deepCopy2:[" + deepCopy2.toString() + "]");

    }

    @Data
    public static class ReferenceObj implements Cloneable {
        private String desc;
        private Integer status;

        @Override
        protected Object clone() throws CloneNotSupportedException {
            return super.clone();
        }
    }
}

相同点

都必须实现Cloneable接口和复写Object的clone方法
开辟新的内存供新对象存放

区别

浅拷贝只做部分拷贝,深拷贝是全量拷贝
浅拷贝实现更简单,耗时短,存在新对象和源对象引用变量相互影响隐患;深拷贝实现复杂些,耗时长