浅拷贝和深拷贝的区别

java 复制代码
        Person p1 = new Person(10);
        Person p2 = p1;
        p2.age = 20;

        System.out.println(p1=p2); // true
        System.out.println(p1.age); // 20

这种做法只是复制了对象的地址,即两个变量现在是指向了同一个对象,任意一个变量,操作了对象的属性,都会影响到另一个变量

这中对同一个对象操作,当然算不上真正的复制,所以引用拷贝并不算对象拷贝,所谓的对象拷贝一般就是指浅拷贝和深拷贝

浅拷贝

在java中Object提供了一个clone()方法,看名字就是它和对象拷贝有关,该方法访问修饰符为protected,如果子类不重写该方法,并将其声明为public,那外部就调用不了,对象的clone().

java 复制代码
class Person implements Cloneable {
    public int age;

    public Person(int age) {
        this.age = age;
    }

    @Override
    public Person clone() {
        try {
            return (Person) super.clone();  
        } catch (CloneNotSupportedException e) {
            throw new RuntimeException(e);
        }
    }
}

子类在重写时直接调用Object的clone()即可,它是native方法,底层实现了拷贝对象的逻辑,注意子类一定得实现Cloneable接口,否则调用clone()时,会抛出异常,这是java的规定。

java 复制代码
        Person p1 = new Person(10);
        Person p2 = p1;
        p2.age = 20;

        System.out.println(p1=p2); // false
        System.out.println(p1.age); // 10

现在我们调用clone()方法来实现,发现两个变量指向的已经是不同的对象各自改属性,也不会影响到另一个对象,看起来效果很好。

不过有一个问题,如果拷贝对象中有属性是引用类型,那这种浅拷贝的方式,只会复制该属性的引用地址,即拷贝对象和原对象的属性,都指向了同一个对象,如果对这个属性进行一些操作,则会影响到另一个对象的属性,若想将对象中的引用类型属性也进行拷贝,那就得用深拷贝了。

深拷贝

java 复制代码
class Person implements Cloneable {
    public int age;
    public int[] arr = new int[]{1,2,3}

    public Person(int age) {
        this.age = age;
    }

    @Override
    public Person clone() {
        try {
           Person person = (Person) super.clone();  
           person.arr = this.arr.clone();
           return perosn;
        } catch (CloneNotSupportedException e) {
            throw new RuntimeException(e);
        }
    }
}

我们将clone()方法稍微修改一下,clone()出对象之后,我们再对对象的属性,进行一次拷贝。

这样就完成了属性的复制,此时对象中的属性也指向了不同的对象实例。

总结

引用拷贝只是复制对象的地址,并不会创建一个新的对象

浅拷贝会创建一个对象,并进行属性的复制,不过对引用类型的属性,只会复制其对象地址

深拷贝则是完全复制整个对象,包括引用类型的属性

都是通过clone(),在实际开发中,不建议大家使用该方法,因为他有抛出异常的风险,如果真的想让对象提供拷贝功能,可以自己编写其他方法来实现

相关推荐
DanmF--7 分钟前
C#面向对象实践项目--贪吃蛇
开发语言·游戏·c#·游戏程序
@老蝴18 分钟前
C语言 — 动态内存管理
android·c语言·开发语言
.生产的驴23 分钟前
SpringCloud 分布式锁Redisson锁的重入性与看门狗机制 高并发 可重入
java·分布式·后端·spring·spring cloud·信息可视化·tomcat
虾球xz37 分钟前
CppCon 2014 学习:C++ Memory Model Meets High-Update-Rate Data Structures
java·开发语言·c++·学习
攒了一袋星辰39 分钟前
Spring @Autowired自动装配的实现机制
java·后端·spring
小灰灰搞电子44 分钟前
Qt 仪表盘源码分享
开发语言·qt
我的golang之路果然有问题1 小时前
快速了解GO+ElasticSearch
开发语言·经验分享·笔记·后端·elasticsearch·golang
Bug缔造者1 小时前
若依+vue2实现模拟登录
java·前端框架
凤年徐1 小时前
【数据结构初阶】顺序表的应用
c语言·开发语言·数据结构·c++·笔记·算法·顺序表
麦兜*1 小时前
【后端架构师的发展路线】
java·spring boot·spring·spring cloud·kafka·tomcat·hibernate