java对象拷贝

概念

对象拷贝分为浅拷贝和深拷贝;
浅拷贝:只拷贝了源对象指向堆空间中内存地址,所以源对象的值发生变化时,拷贝对象的值也会发生变化;
深拷贝:源对象和新对象指向堆空间中内存地址不同,即使源对象的值发生变化时,拷贝对象的值也不会改变

浅拷贝

1)直接赋值

Object a=new Object();
Object b=a;

这样只是将对象a的引用地址赋值给了b,当a对象值改变的时候,b对应的值也会改变
2)使用Cloneable,重写clone方法实现浅拷贝
首先创建两个类

@Data
@AllArgsConstructor
public class Persion implements Cloneable{

    private String name;

    private Integer age;

    private Course course;

    @Override
    public Persion clone() throws CloneNotSupportedException {
        Persion persion = (Persion) super.clone();
        return persion;
    }
}
@Data
@AllArgsConstructor
public class Course {

    private String courseName;

    private Integer score;
}

测试

    public static void main(String[] args) throws CloneNotSupportedException {
        Course course=new Course("语文",60);
        Persion red=new Persion("小红",10,course);
        Persion black=red.clone();
        black.setName("小明");
        black.getCourse().setCourseName("数学");
        System.out.println(black.getName()+"   "+black.getCourse().getCourseName()+"   "+black.hashCode()+"   "+black.getCourse().hashCode());
        System.out.println(red.getName()+"   "+red.getCourse().getCourseName()+"   "+red.hashCode()+"   "+red.getCourse().hashCode());
    }

结果:

小明   数学   -1611798689   48879495
小红   数学   -1589896237   48879495

结论:重写Cloneable的clone方法,只能拷贝当前对象,对于该对象引用的对象并没有改变;
如果要当前对象的引用也拷贝则需要当前对象的引用对象也实现Cloneable的接口,重写clone方法;
3)使用Spring提供的copyProperties方法实现浅拷贝

        Course course=new Course("语文",60);
        Persion red=new Persion("小红",10,course);
        Persion black=new Persion();
        BeanUtils.copyProperties(red,black);
        black.setName("小明");
        black.getCourse().setCourseName("数学");
        System.out.println(black.getName()+"   "+black.getCourse().getCourseName()+"   "+black.hashCode()+"   "+black.getCourse().hashCode());
        System.out.println(red.getName()+"   "+red.getCourse().getCourseName()+"   "+red.hashCode()+"   "+red.getCourse().hashCode());

结果:

小明   数学   -1611798689   48879495
小红   数学   -1589896237   48879495

深拷贝

深拷贝对引用数据类型的成员变量中的所有的对象都开辟了内存空间,创建内存空间和拷贝整个对象,深拷贝相比于浅拷贝速度较慢并且花销较大。
1)使用Cloneable,重写clone方法实现深拷贝
即是将当前对象应用的所有对象都实现Cloneable并重写clone方法,但是这样比较麻烦;不常用

序列化实现深拷贝

2)使用apache的SerializationUtils实现深拷贝

Persion black=SerializationUtils.clone(red);

结果:

小明   数学   -1611798689   48879495
小红   语文   -1571722113   67053619

可以看到,Persion的hashCode和Course的hashCode都发生了变化,说明当前类中的引用类也是在内存中重新开辟空间存储;
注意:SerializationUtils.clone()中的类要实现Serializable接口
3)使用fastjson进行序列化

Persion black= JSONObject.parseObject(JSONObject.toJSONString(red),Persion.class);

结果

小明   数学   -1611798689   48879495
小红   语文   -1571722113   67053619

其它json也都是深拷贝

使用序列化进行拷贝对象的注意事项

静态成员变量、被transient修饰的成员变量 在序列化时是不会被序列化的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值