java对象深拷贝的三种实现方式,可避免循环引用导致的堆栈溢出

createh52个月前 (02-01)技术教程16

在java编程中,难免要对一个对象进行复制,复制分为深拷贝和浅拷贝。

浅拷贝只复制对象本身,对于对象引用的其他对象不进行复制。
深拷贝则将对象与引用对象,全部进行拷贝。

最简单的深拷贝就是自己new一个对象,然后进行赋值,但是过于繁琐。

这里介绍三种深拷贝方式。

准备两个对象:

@Setter
@Getter
@ToString
public class Order implements Cloneable, Serializable {

    private String orderId;

    private String goodsId;

    private BigDecimal goodsNum;

    private OrderInvoice orderInvoice;

    @Override
    public Order clone() throws CloneNotSupportedException {
        Order order= (Order)super.clone();
        OrderInvoice orderInvoiceClone = orderInvoice.clone();
        orderInvoiceClone.setOrder(order);
        order.setOrderInvoice(orderInvoiceClone);
        return order;
    }

}
@Setter
@Getter
@ToString(exclude = "order")
@EqualsAndHashCode(exclude = "order")
public class OrderInvoice implements Cloneable, Serializable {

    private String invoiceId;

    private Order order;

    @Override
    public OrderInvoice clone() throws CloneNotSupportedException {
        return (OrderInvoice)super.clone();
    }
}

注意,这两个对象存在互相引用的,order中有invoice,而invoice中又有order。

使用google提供的Gson会导致堆栈溢出,如果没有循环引用可以考虑这种方式。

Gson gson = new Gson();
Order order=  gson.fromJson(gson.toJson(order),Order.class);


对相互引用无感的三种方式

1、实现clonable接口,重写Object.clone()方法,注意此方法为protected,重写时需要改为public,代码很简单,如下:

    public static  void cloneOrder(Order order) throws CloneNotSupportedException {
        Order cloneOrder = order.clone();
        log.info("cloneOrder :",cloneOrder);
    }

这里可以看到生成两个order,内存地址不一样,说明不是同一个对象。

2、使用阿里巴巴fastJson

    public static  T deepCopyByJson(T obj,Class t) {
        String json = JSON.toJSONString(obj);
        return JSON.parseObject(json, t);
    }

3、使用
org.apache.commons.lang.SerializationUtils,当然,这个对象需要实现Serializable接口,使用很简单只要一句即可

Order clone = (Order) SerializationUtils.clone(order);

以上就是介绍的三种方式,用好工具类,事半功倍。

学代码很容易觉得学不动了,东西太多了。记得这些东西都是解决方案,不懂去查就好,不要有太大心里负担。毕竟咱们都是站在巨人的肩膀上,看不懂源码,那就先会用就好。

相关文章

你知道Java的对象拷贝方式有哪几种吗?

【死记硬背】总共有四种,分别是直接赋值拷贝、浅拷贝、深拷贝和序列化。直接赋值拷贝:这个实际上复制的是对象的引用地址,如:Person p1 = p2,则p1和p2指向的是同一个对象的地址。因此,p1属...

Java的深拷贝与浅拷贝详解(java的深拷贝与浅拷贝详解图)

前言拷贝,顾名思义,就是复制一个一模一样的东西。那么放到对象上,也就是复制一个一模一样的对象了。Java中的数据类型分为基本数据类型和引用数据类型。对于这两种数据类型,在进行赋值操作、用作方法参数或返...

Java常用的几种属性拷贝工具类使用总结

Java属性拷贝工具类使用总结对项目中经常使用的属性拷贝工具类进行总结:org.apache.commons.beanutils.BeanUtilsorg.apache.commons.beanuti...

几种实体拷贝方式实战(拷贝如何使用)

背景我们有这样一个场景,有一个StudentDto类,还有一个StudentVo类@Datapublic class StudentDto { private String id; private S...

日拱一卒:Java 如何实现对象的 clone?

大家好,我是菜菜,一个为 coding 而生,为 debug 奋斗一辈子的地地道道的码农。日拱一卒系列,旨在通过对 Java 后端常见的面试题进行剖析,少走弯路,利用有限的精力,更加高效的准备和学习。...

Java 简单易用的深拷贝开源库(java深拷贝工具)

浅拷贝是指在对一个对象进行拷贝时,只拷贝对象本身和其中的基本数据类型,而不拷贝对象内部的引用类型。因此,在浅拷贝的对象中,引用类型的变量指向的依旧是原始对象中的引用。深拷贝是指在对一个对象进行拷贝时,...