什么是浅拷贝?如何使用深拷贝

1、首先了解

在学习浅拷贝和深拷贝前,我们需要先了解什么是引用类型和基本类型。

1.1、引用类型和基本类型

1、引用类型:引用类型的变量保存引用值,所谓的引用值就是对象所在内存空间的“首地址值”,通过对这个引用值来操作对象。

常见的引用类型:类类型,接口类型、数组(eg:char[])、String类

2、基本类型:基本类型的变量保存原始值,所以变量就是数据本身。

常见的基本类型:byte、short、int、long、char、float、double、Boolean。

1.2、值传递和引用传递

值传递: 在方法的调用过程中,实参把它的实际值传递给形参,此传递过程就是将实参的值复制一份传递到函数中,这样如果在函数中对该值(形参的值)进行了操作将不会影响实参的值。因为是直接复制,所以这种方式在传递大量数据时,运行效率会特别低下。

注意:String、BigInteger、BigDecimal以及包装器类型:Integer、Long、Short、Byte、Character、Boolean、Float和Double等不可变类都视为值传递。

引用传递: 引用传递就是将对象的地址值传递过去,函数接收的是原始值的首地址值。在方法的执行过程中,形参和实参的内容相同,指向同一块内存地址,也就是说操作的其实都是源数据,所以方法的执行将会影响到实际对象。

2、浅拷贝

理解:对基本数据类型进行值传递,对引用数据类型进行引用传递般的拷贝。

2.1、浅拷贝方法

2.1.1实现 Cloneable 接口

对需要拷贝的对象类实现 Cloneable 接口,如果对象中存在对其他类的引用,也需要实现cloneable接口。
示例:

@Data
class Person implements Cloneable{
    private String name;
    private Integer age;
    @Override
    protected Object clone() throws CloneNotSupportedException  {
        return super.clone();
    }
}

问题: 拷贝对象中存在对其他对象的引用,则其他对象是拷贝的首地址值,相当于引用传递,源对象和拷贝对象对引用对象修改,都会修改统一数据源。

3、深拷贝

理解:对基本数据类型进行值传递,对引用数据类型,创建一个新的对象,并复制其内容。

3.1、深拷贝方法

3.1.1、方法一:实现 Cloneable 接口并重写clone方法

@Data
class User implements Cloneable{
    private String name;
    private Dog dog;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        User u=(User) super.clone();
        u.dog=(Dog) dog.clone(); 
        return u;
    }
}

可实现深拷贝,但每个拷贝对象都需要重写clone方法,代码相当繁琐。

3.1.2、方法二:实现Serializable接口,通过对象的序列化和反序列化实现克隆

       private static <T>T  CloneObj(T obj){
            T retobj=null;
            try {
            //写入流中
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(baos);
            oos.writeObject(obj);
            //从流中读取
            ObjectInputStream ios = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));
            retobj=(T) ios.readObject();
            }catch (Exception e) {
                e.printStackTrace();
            }
            return retobj;
        }

高级写法

    @SneakyThrows
    @Deprecated
    @SuppressWarnings("unchecked")
    public static <T extends Serializable> T deepClone(T t) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        @Cleanup ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(t);
        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
        @Cleanup ObjectInputStream ois = new ObjectInputStream(bais);
        return (T) ois.readObject();
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值