java深拷贝和浅拷贝(亲自实验后的总结!)

一、概念辨析

浅拷贝是只拷贝源对象中的非对象属性(基本类型属性),对于对象属性,只拷贝它们的引用。同时,对于那些不可变的对象属性,如String类属性,修改这些属性并不会影响源对象中的这些属性值。
深拷贝不仅复制主对象,还复制它所引用的对象

二、实现方式

1、浅拷贝需要类实现cloneable接口,并覆写clone方法,方法体中返回super.clone();
如下所示:

class Student implements Cloneable{
    private String name;
    private int age;
    private Teacher teacher;
    //getter,setter,构造方法略
    @Override
    public Object clone() throws CloneNotSupportedException {//浅拷贝
    	return super.clone();
    }

使用方法:

Student stu1 = new Student("xiaowang", 25, teacher);
Student stu2 = stu1.clone();

2、深拷贝有两种实现方式,一种是对象、对象的对象等逐层实现cloneable接口并覆写clone方法,同时在覆写时,要通过对象属性的clone方法重新对对象属性赋值,这样才能生成一个新的对象属性。该方法的缺点在于,如果对象存在嵌套引用,即对象甲引用对象乙,对象乙又引用对象丙等等,在这样的情况下,每个有引用对象的类都需要实现深拷贝功能;同时如果类中有多个引用对象,那在覆写clone方法时需要对每个对象都进行set。如下所示:

class Student implements Cloneable{
    private String name;
    private int age;
    private Teacher teacher;
    //getter,setter,构造方法略
    @Override
    public Object clone() throws CloneNotSupportedException {  //深拷贝
    	Student student = (Student) super.clone();  //先进行浅拷贝
        student.setTeacher((Teacher)student.getTeacher().clone());  //再将student的teacher对象复制一份,
        // 这个新的teacher对象再赋给student,这样就实现了对象复制,而不是引用复制了。
        return student;
    }

第二种是通过将对象序列化,写进一个字节流中,然后再从字节流中读出来,反序列化生成一个新的对象拷贝,即深拷贝。该方法相较于第一种更简单,但是仍需要各对象类逐层实现Serializable接口,这只是一个标记接口,不需要覆写任何方法。如果读者想要试验这种方法,只需要自己写一个类,这个类及它的对象类要实现Serializable接口,然后就可以调用下面的函数实现深拷贝:

public class CloneUtils {
    @SuppressWarnings("unchecked")
    public static <T extends Serializable> T clone(T obj){  //深拷贝
        T cloneObj = null;
        try {
            //写入字节流
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            ObjectOutputStream obs = new ObjectOutputStream(out);
            obs.writeObject(obj);
            obs.close();
            
            //分配内存,写入原始对象,生成新对象
            ByteArrayInputStream ios = new ByteArrayInputStream(out.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(ios);
            //返回生成的新对象
            cloneObj = (T) ois.readObject();
            ois.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return cloneObj;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值