java clone深拷贝与浅拷贝

使用场景:

如果要进行对象clone的话,需要实现Cloneable接口,并调用.clone方法。

实现:

在进行clone的过程中,需要注意如果拷贝的是引用类型的对象(String除外),都是拷贝的地址,而不是拷贝的值。这样做的缺点就是如果改变了克隆的对象的值,被克隆对象的值也会被修改,因为都指向的是同一块堆中的数据。

看一下下面的代码

public class CloneTest  implements Cloneable{

    private Student student;

    private Integer num;

    public static void main(String[] args) {
        CloneTest cloneTest = new CloneTest();
        cloneTest.setNum(1);
        Student s = new Student();
        s.setName("zhangsan");
        s.setSex("nan");
        cloneTest.setStudent(s);
        try {
            CloneTest clone = (CloneTest)cloneTest.clone();
            System.out.println(clone.getStudent() == cloneTest.getStudent());
            Student student = clone.getStudent();
            student.setName("zhangsan-changed");
            System.out.println(clone.getStudent().getName());
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
    }

    public Student getStudent() {
        return student;
    }

    public void setStudent(Student student) {
        this.student = student;
    }

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

    public Integer getNum() {
        return num;
    }

    public void setNum(Integer num) {
        this.num = num;
    }
}

class Student{
    private String name;

    private String sex;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }
}

输出的结果是

说明student指向的还是同一个对象,所以修改了克隆对象的student,被克隆对象的student也被修改,如果不注意的话,可能就会出现问题。

解决:

为了解决浅克隆出现的问题,可以有以下几种方法:

1 通过json工具类的转换(先转为json字符串,再转回原有类的对象),因为基本上都是通过反射来创建引用对象,即new出来了一个新的对象,所以可以解决。

2 通过序列化,需要类实现Serializable接口,通过io流的方式来实现

        //将对象写入流中
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
        objectOutputStream.writeObject(cloneTest);
        //从流中取出
        ByteArrayInputStream inputStream = new                         
        ByteArrayInputStream(outputStream.toByteArray());
        ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
        CloneTest cloneObj = (CloneTest) objectInputStream.readObject();
        System.out.println(cloneObj.getStudent() == cloneTest.getStudent());

也可以使用工具类

        byte[] serialize = SerializationUtils.serialize(cloneTest);
        CloneTest deserialize = (CloneTest) SerializationUtils.deserialize(serialize);
        System.out.println(deserialize.getStudent() == cloneTest.getStudent());

3 手动赋值,将被克隆对象的引用类型的成员变量拿出来,new,并进行手动赋值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

每年进步一点点

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值