深拷贝 / 浅拷贝

文章通过一个学生类示例,解释了Java中深拷贝和浅拷贝的区别。浅拷贝只复制对象的基本类型属性,而引用类型属性仍指向原对象。深拷贝则会创建新的引用类型实例,确保拷贝后的对象与原对象完全独立。在处理包含复杂引用结构的对象时,深拷贝能保证数据的安全性,避免修改原对象影响拷贝后的对象。
摘要由CSDN通过智能技术生成

复制一个对象时,对象的属性使用深拷贝更合理,浅拷贝可能会出一些问题

  • 浅拷贝:拷贝了对象的基本类型属性,引用类型属性仅拷贝了引用;
  • 深拷贝:不仅仅拷贝了对象的基本类型,引用类型的属性还进行了对象的克隆拷贝 。
//主体类
//学生类
public class Student { 
    private String name; //name是引用类型
    private int age0; //age0是基本类型
    private MyInt age; //age是引用类型
    private String clazz; //clazz是引用类型
    //toString和Getter&Setter方法不再显示
}

//MyInt引用类型代替基本类型int用于测试
public class MyInt {
    private int value;

    public MyInt(int value) {
        this.value = value;
    }
    //toString和Getter&Setter方法不再显示
}

测试及结果

浅拷贝ShallowCopy

/**
     * 浅拷贝方式,拷贝一个学生对象
     * @param stu 待拷贝的原对象
     * @return 拷贝后的新对象
     */
    public static Student shallowCopy(Student stu){
        Student newStu = new Student();

        newStu.setName(stu.getName());
        newStu.setAge0(stu.getAge0());
        newStu.setAge(stu.getAge());
        newStu.setClazz(stu.getClazz());

        return newStu;
    }
//测试
public static void testShallowCopy(){
        Student stu = new Student();
        stu.setName("张三");
        stu.setAge0(10);
        stu.setAge(new MyInt(25));
        stu.setClazz("软件1班");

        System.out.println("待拷贝的原学生对象:" + stu);

        Student shallowStu = shallowCopy(stu);

        System.out.println("浅拷贝出的学生对象:" + shallowStu);

        System.out.println("下面开始改变姓名、年龄:");
        stu.setName("李四");
        stu.setAge0(11);//浅拷贝基本类型
        stu.getAge().setValue(28);//只改变了老学生对象的年龄,未改变新拷贝出的学生对象的年龄
        //(但是结果二者都显示的同一数值,拷贝后的数值跟拷贝前原数值改变后的数值一样)

        System.out.println("改变后,原学生对象:" + stu);
        System.out.println("新学生对象:" + shallowStu);
    }

结果显示:

待拷贝的原学生对象:Student{name='张三', age0=10, age=MyInt{value=25}, clazz='软件1班'}
浅拷贝出的学生对象:Student{name='张三', age0=10, age=MyInt{value=25}, clazz='软件1班'}

值一样,但是是两个对象
下面开始改变年龄:下面开始改变名字、年龄:
改变后,原学生对象:Student{name='李四', age0=11, age=MyInt{value=26}, clazz='软件1班'}
新学生对象:Student{name='张三', age0=10, age=MyInt{value=26}, clazz='软件1班'}

浅拷贝的为新对象,改原对象中的基本类型,浅拷贝的新对象中的基本类型不变(原因:常量变量的本质区别(常量只能赋值一次,变量可以赋值多次;常量在程序运行过程中不能改变,变量可以改变。

​​​​​​​浅拷贝后的对象引用类型还是指向原地址(地址占内存),内容不变,基本类型改变

类似浅拷贝只是学习了某人炒股的能力,但是此后该人的盈亏也能体现在你的账户上​​​​​​​

深拷贝DeepCopy

内存分开了,费内存,但是安全性高

//补充主体类
public class MyInt {
    private int value;

    public MyInt(int value) {
        this.value = value;
    }

    @Override
    public String toString() {
        return "MyInt{" +
                "value=" + value +
                '}';
    }

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }
}
/**
     * 深拷贝方式,拷贝一个学生对象
     * @param stu 待拷贝的原对象
     * @return 拷贝后的新对象
     */
    public static Student deepCopy(Student stu){
        Student newStu = new Student();

        //深拷贝的关键之处,在于引用类型的属性,要指向新的对象!!!
        newStu.setName(new String(stu.getName()));
        MyInt newAge = new MyInt(stu.getAge().getValue());
        newStu.setAge(newAge);
        newStu.setClazz(new String(stu.getClazz()));

        return newStu;
    }
//测试
public static void testDeepCopy(){
        Student stu = new Student();
        stu.setName("张三");
        stu.setAge0(10);
        stu.setAge(new MyInt(25));
        stu.setClazz("软件1班");

        System.out.println("待拷贝的原学生对象:" + stu);

        Student shallowStu = deepCopy(stu);

        System.out.println("深拷贝出的学生对象:" + shallowStu);

        System.out.println("下面开始改变名字、年龄:");
        stu.setName("李四");
        stu.setAge0(11);
        stu.getAge().setValue(28);//只改变了老学生对象的年龄,未改变新拷贝出的学生对象的年龄

        System.out.println("改变后,原学生对象:" + stu);
        System.out.println("新学生对象:" + shallowStu);//原对象改变值后,新的对象值不会随着原对象的值改变而改变
    }

结果显示:

待拷贝的原学生对象:Student{name='张三', age0=10, age=MyInt{value=25}, clazz='软件1班'}
深拷贝出的学生对象:Student{name='张三', age0=0, age=MyInt{value=25}, clazz='软件1班'}
下面开始改变名字、年龄:
改变后,原学生对象:Student{name='李四', age0=11, age=MyInt{value=28}, clazz='软件1班'}
新学生对象:Student{name='张三', age0=0, age=MyInt{value=25}, clazz='软件1班'}

 注意

假深拷贝,指向新的对象,但是新的对象往下还是引向同一个对象(深拷贝和原对象指向的对象都是一一对应),字符串和八种包装类不需要深拷贝,因为设计为内容不可变,变的只有引用指向新对象,而不是对象内容的改变。


深拷贝、浅拷贝归根结底其实是基本类型,引用类型,对象的区别

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值