JAVA中的深拷贝和浅拷贝

对于一个对象的拷贝,有很多方法,比如最简单的

就是这个类实现 cloneable接口,实现clone()方法即可,

但是这样是浅拷贝,意思就是对象的基础类型和引用对象的句柄都拷贝过去了

注意 这里说的是引用对象的句柄

但是,学过JVM的都知道,基础类型都是存放在JAVA栈中,

引用类型:句柄存放在栈中,对象是存在放堆中

所以你如果修改1个对象的引用,相当于修改了2个对象的应用。

因为浅拷贝的目标对象和源对象指向的引用成员变量是同一个地方。

所以我们需要深拷贝,意思就是拷贝的时候,同时把引用对象也拷贝出一份

用对象字节流的序列与反序列化很方便,下面是例子

Student.java

@Data
@Builder
public class Student implements Cloneable,Serializable{

    private static final long serialVersionUID = 2L;

    private String Name;
    private String sex;
    private Classes classes;

    /**
     * 浅拷贝
     * @return
     * @throws CloneNotSupportedException
     */
    @Override
    protected Student clone() throws CloneNotSupportedException {
        return (Student)super.clone();
    }

    /**
     * 深度拷贝 == 不管你对象中是值类型部分,还是引用类型部分,我全部拿走
     * 对象字节流的序列与反序列化 ==> 对象完全、深度、彻彻底底的Copy!!!
     * @return
     */
    public Student deepClone(){

        // Anything 都是可以用字节流进行表示,记住是任何!
        Student student = null;
        try{

            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(baos);
            // 将当前的对象写入baos【输出流 -- 字节数组】里
            oos.writeObject(this);

            // 从输出字节数组缓存区中拿到字节流
            byte[] bytes = baos.toByteArray();

            // 创建一个输入字节数组缓冲区
            ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
            // 创建一个对象输入流
            ObjectInputStream ois = new ObjectInputStream(bais);
            // 下面将反序列化字节流 == 重新开辟一块空间存放反序列化后的对象
            student = (Student) ois.readObject();

        }catch (Exception e){
            System.out.println(e.getClass()+":"+e.getMessage());
        }
        return  student;
    }
}

测试类

public static void main(String[] args) throws CloneNotSupportedException {

        Classes classes = Classes.builder().classesName("classname")
                .classesLeavl(1).build();
        Student student1 = Student.builder().Name("aaa")
                            .sex("男").classes(classes).build();

        Student student2 = student1.clone();
        classes.setClassesName("classnamenew");
        student1.setName("bbbb");

        Student student3 = student1.deepClone();
        classes.setClassesName("classname333");
        student1.setName("cccc");

        System.out.println("student1.classes"+student1.getClasses().hashCode());
        System.out.println("student1"+student1.getClasses());
        System.out.println("student2.classes"+student2.getClasses().hashCode());
        System.out.println("student2"+student2.getClasses());
        System.out.println("student3.classes"+student3.getClasses().hashCode());
        System.out.println("student3"+student3.getClasses());
    }

打印结果

student1.classes1185899242
student1Classes(classesName=classname333, classesLeavl=1)
student2.classes1185899242
student2Classes(classesName=classname333, classesLeavl=1)
student3.classes1189339945
student3Classes(classesName=classnamenew, classesLeavl=1)

从结果可以看到,student2是student1的浅拷贝对象,修改classes对象时,同时也影响到student2

                             student3是student1的深拷贝对象,修改classes对象时,不会影响到student3.

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值