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

createh54个月前 (02-01)技术教程22

在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);

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

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

相关文章

你还在用BeanUtils进行对象属性拷贝?

在做业务的时候,为了隔离变化,我们会将DAO查询出来的DO和对前端提供的DTO隔离开来。大概90%的时候,它们的结构都是类似的;但是我们很不喜欢写很多冗长的b.setF1(a.getF1())这样的代...

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

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

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

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

④ JAVA IO—拷贝(java拷贝文件夹到另外一个文件夹)

一、 传统的IO1. 数据由磁盘拷贝到内核空间(DMA),再由内核空间拷贝到用户空间(JVM)2. 用户可能会对拷贝进来的数据进行操作3. 数据从用户空间拷贝到内核空间(JVM),再通过内核空间将数据...

Java中深拷贝、浅拷贝、赋值的区别?如何自己写个深拷贝工具类?

#头条创作挑战赛#为什么要了解JavaBean深拷贝的机制目前大家都在常用已经封装好的工具类,很少去深入了解多种实现方式;此处提出一种简单的实现原理,也是巩固Java中关于反射的用法和知识;目的:可以...