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

java堆溢出排查流程(java对象深拷贝的三种实现方式)(1)

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

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

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

java堆溢出排查流程(java对象深拷贝的三种实现方式)(2)

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

2、使用阿里巴巴fastJson

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

java堆溢出排查流程(java对象深拷贝的三种实现方式)(3)

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

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

java堆溢出排查流程(java对象深拷贝的三种实现方式)(4)

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

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

,