Java 对象深度拷贝问题

在功能模块的实现中,需要对一个变量进行深度拷贝,该变量是一个存储二维Map的对象,之前同事写了一个用序列化进行深度拷贝的方法。

在一般的业务情况下,没有发现问题,但是在进行性能测试时,对象大小会达到1~2MB,在进行对象深度拷贝时,会有异常抛出java.io.OptionalDataException,导致对象拷贝失败,影响程序的正确性。

错误日志如下:

[E] 05/31 09:58:10,247 RouteService(1517) - [ROU]动态路由copy异常! e.toString = java.io.OptionalDataException 
e.getStackTrace = [
java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1373), java.io.ObjectInputStream.readObject(ObjectInputStream.java:373), java.util.HashMap.readObject(HashMap.java:1402), sun.reflect.GeneratedMethodAccessor8.invoke(Unknown Source), sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43), java.lang.reflect.Method.invoke(Method.java:498), java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1058), java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1909), java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1808), java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1353), java.io.ObjectInputStream.readObject(ObjectInputStream.java:373), 
com.qsd.common.utils.CopyMapUtil.clone(CopyMapUtil.java:28), ==============ObjectInputStream.readObject
com.qsd.route.main.RouteService.updateRouteTable(RouteService.java:1515), com.qsd.route.main.RouteService.updateQuantumRoute(RouteService.java:667), com.qsd.route.main.RouteCalculationThread.action(RouteCalculationThread.java:124), com.qsd.common.utils.PersistentThread.run(PersistentThread.java:43)]

于是对又重新复习了一下对象克隆的基本概念,和深度拷贝的方法

1.对象克隆的基本概念,在《Java核心技术-卷一》(原书第九版),第六章 接口与内部类,6.2对象克隆中讲的非常清楚

1)如果被拷贝对象中的所有数据域都属于数值或者基本类型,用Object集成来的clone方法进行拷贝,没有任何问题;

2)如果被拷贝对象中,数据域中包含子对象引用,拷贝的结果会使得两个域引用同一个子对象--因此原始对象和克隆对象共享这个子对象域,没有实现深度拷贝!

2.关于深度拷贝,在网上查了一些资料,有不少同学认为,序列化是一个不错的深度拷贝的实现方式,包括《Java核心技术-卷二》序列化章节,也提到了序列化可以进行对象深度拷贝。但是进行了一些代码分析和调整后,异常还是会出现,所以没有办法,只能使用自定义clone()方法的办法,用循环进行对象的深度拷贝了。需要做的有两步:

1)修改要拷贝对象的类,添加集成克隆接口(implements Cloneable),并添加clone()方法

如果类的成员变量都是Java基本类型,那么clone()方法非常简单,Class1 clone()方法如下:

public Class1 clone() throws CloneNotSupportedException {
    return (Class1) super.clone();
}

如果类的成员变量包含其他类ClassName2的对象,那么就需要给这个类添加clone()方法,一次类推。Class1 clone()方法如下:

public Class1 clone() throws CloneNotSupportedException {
    Class1 cloned = (Class1) super.clone();
	cloned.obj2 = (Class2) obj2.clone();// obj2是Class1的城域变量,类型是Class2
	return cloned;
}

2)在遍历要拷贝对象的集合时,调用clone()方法,实现集合的深度拷贝

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值