直观理解浅拷贝与深拷贝

在完成实验时,明明返回的是一个clone以后的对象,修改这个对象却会把原对象的值也修改了,所以在这里记录以下这个容易犯的错误。

一.引用拷贝

这是最常见的拷贝,只要用“=”就可以完成,也是最简单的拷贝

String a = "Hello World!";
String b = a;

通过debug可以观察到两者指向的是相同的内存单元:
在这里插入图片描述
用图来解释就是这样:
在这里插入图片描述

二.对象拷贝

1.浅层拷贝

被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。简单来说,就是只拷贝第一层的对象,而对象的里的引用则不进行拷贝。例如以下代码:

public class main {

    public static void main(String[] args) throws CloneNotSupportedException {
        MyString a = new MyString("Hello World!");
        MyString b = (MyString) a.clone();
        System.out.println(a);
        System.out.println(b);
    }
}

// 注意这里需要实现Cloneable接口
class MyString implements Cloneable{

    String l;

    public MyString(String a) {
        this.l = a;
    }

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

输出结果为
在这里插入图片描述
而debug进去能够发现:
在这里插入图片描述
指向的都为同一个字符串Hello World存储的内存区域
用图示来理解则是
在这里插入图片描述

2.深层拷贝

深拷贝是一个整个独立的对象拷贝,深拷贝会拷贝所有的属性,并拷贝属性指向的动态分配的内存。当对象和它所引用的对象一起拷贝时即发生深拷贝。深拷贝相比于浅拷贝速度较慢并且花销较大。简而言之,深拷贝把要复制的对象所引用的对象都复制了一遍。
在实现深拷贝时,可以考虑递归得对每一个对象的属性里引用的对象都clone,但是这样当类与类之间的关系比较复杂或属性比较多时,很难操作,故这里使用实现Serializable接口的方法

import java.io.*;

public class main {

    public static void main(String[] args) throws Exception {
        MyString a = new MyString("Hello World!");
        MyString b = (MyString) a.deepClone();
        System.out.println(a);
        System.out.println(b);
    }
}

//注意这里需要实现Serializable接口
class MyString implements Serializable {

    String l;

    public MyString(String a) {
        this.l = a;
    }

    // 深度拷贝
    public Object deepClone() throws Exception{
        // 序列化
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);

        oos.writeObject(this);

        // 反序列化
        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bis);

        return ois.readObject();
    }
}

代码输出
在这里插入图片描述
进入debug进行观察可以发现两个l指向不同的内存空间
在这里插入图片描述
用图来理解则是:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值