[改善Java代码] 推荐使用序列化实现对象的拷贝

建议44: 推荐使用序列化实现对象的拷贝

上一个建议说了对象的浅拷贝问题,实现Cloneable接口就具备了拷贝能力,那我们来思考这样一个问题:如果一个项目中有大量的对象是通过拷贝生成的,那我们该如何处理?每个类都写一个clone方法,并且还要深拷贝?想想看这是何等巨大的工作量呀,是否有更好的方法呢?

其实,可以通过序列化方式来处理,在内存中通过字节流的拷贝来实现,也就是把母对象写到一个字节流中,再从字节流中将其读出来,这样就可以重建一个新对象了,该新对象与母对象之间不存在引用共享的问题,也就相当于深拷贝了一个新对象,代码如下:

 1 public class CloneUtils {  
 2      // 拷贝一个对象  
 3      @SuppressWarnings("unchecked")  
 4      public static <T extends Serializable>  T clone(T obj) {  
 5           // 拷贝产生的对象  
 6           T clonedObj = null;  
 7           try {  
 8             // 读取对象字节数据  
 9             ByteArrayOutputStream baos = new ByteArrayOutputStream();  
10             ObjectOutputStream oos = new ObjectOutputStream(baos);  
11             oos.writeObject(obj);  
12             oos.close();  
13             // 分配内存空间,写入原始对象,生成新对象  
14             ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());  
15             ObjectInputStream ois = new ObjectInputStream(bais);  
16             //返回新对象,并做类型转换  
17             clonedObj = (T)ois.readObject();  
18             ois.close();  
19          } catch (Exception e) {  
20             e.printStackTrace();  
21          }  
22          return clonedObj;  
23      }  
24 } 

此工具类要求被拷贝的对象必须实现Serializable接口,否则是没办法拷贝的(当然,使用反射那是另外一种技巧),上一个建议中的例子只要稍微修改一下即可实现深拷贝,代码如下:

 1 public class CloneUtils {  
 2     // 拷贝一个对象  
 3     @SuppressWarnings("unchecked")  
 4     public static <T extends Serializable>  T clone(T obj) {  
 5          // 拷贝产生的对象  
 6          T clonedObj = null;  
 7          try {  
 8            // 读取对象字节数据  
 9            ByteArrayOutputStream baos = new ByteArrayOutputStream();  
10            ObjectOutputStream oos = new ObjectOutputStream(baos);  
11            oos.writeObject(obj);  
12            oos.close();  
13            // 分配内存空间,写入原始对象,生成新对象  
14            ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());  
15            ObjectInputStream ois = new ObjectInputStream(bais);  
16            //返回新对象,并做类型转换  
17            clonedObj = (T)ois.readObject();  
18            ois.close();  
19         } catch (Exception e) {  
20            e.printStackTrace();  
21         }  
22         return clonedObj;  
23     }  
24 } 

此工具类要求被拷贝的对象必须实现Serializable接口,否则是没办法拷贝的(当然,使用反射那是另外一种技巧),上一个建议中的例子只要稍微修改一下即可实现深拷贝,代码如下:

1 class Person implements Serializable{  
2      private static final long serialVersionUID = 1611293231L;  
3      /*删除掉clone方法,其他代码保持不变*/  
4 } 

上去的,然后我们就可以通过CloneUtils工具进行对象的深拷贝了。用此方法进行对象拷贝时需要注意两点:

(1)对象的内部属性都是可序列化的

如果有内部属性不可序列化,则会抛出序列化异常,这会让调试者很纳闷:生成一个对象怎么会出现序列化异常呢?从这一点来考虑,也需要把CloneUtils工具的异常进行细化处理。

(2)注意方法和属性的特殊修饰符

比如final、static变量的序列化问题会被引入到对象拷贝中来(参考第1章),这点需要特别注意,同时transient变量(瞬态变量,不进行序列化的变量)也会影响到拷贝的效果。

当然,采用序列化方式拷贝时还有一个更简单的办法,即使用Apache下的commons工具包中的SerializationUtils类,直接使用更加简洁方便。

 

转载于:https://www.cnblogs.com/DreamDrive/p/5430981.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/490836.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MATLAB(五)在线性代数中的应用

MATLAB在线性代数中的应用 &#xff08;一&#xff09;向量组的线性相关性 求列向量组A的一个最大线性无关组&#xff0c;可用命令rref(A)将A化成行最简形&#xff0c;其中单位向量对应的列向量即为最大线性无关组所含向量&#xff0c;其他列向量的坐标即为其对应向量用最大线…

C++一位的字符数字转数字

char c4; //1,2,3,.....9 int num0; num int(c - 0);’0’的ASC码是48,‘1’&#xff0c;‘2’......的ASC码分别为49,50...... 和0相减即为对应的数字

关于无穷大量的选择

在解题时候&#xff0c;通常有遇到设置为无穷大的情况。这时候通常用0x7fffffff来设置&#xff0c;他是计算机32位整数最大数&#xff0c;相当于INT_MAX.但是在很多时候这样设置并不会是最佳的&#xff0c;还可能导致bug,这是由于我们有的时候希望无穷大无穷大无穷大&#xff0…

全球市值最大公司的巨变:20年,已是沧海桑田

来源&#xff1a; 资本实验室三十年河东&#xff0c;三十年河西。而商业的世界&#xff0c;变化来得更为迅猛、激烈。就比如当我们比较1999到2019年间的全球市值最大公司&#xff0c;并回看二十年时&#xff0c;惊觉已是沧海桑田。如果以更短的五年为一个观察周期&#xff0c;则…

python+OpenCV图像处理(六)图像平滑与滤波

图像平滑与滤波 运用它&#xff0c;首先就要了解它&#xff0c;什么是平滑滤波&#xff1f; 平滑滤波是低频增强的空间域滤波技术。它的目的有两类&#xff1a;一类是模糊&#xff1b;另一类是消除噪音。空间域的平滑滤波一般采用简单平均法进行&#xff0c;就是求邻近像元点的…

pytorch每次迭代训练前都重新对数据集进行采样形成平衡数据集

对于不平衡数据集的训练通常有两种方法&#xff1a; 一种是先用数据平衡的方法形成平衡数据集之后用于每一轮的训练&#xff0c;此时每轮训练的数据集是不变的&#xff0c;这一方法在pytorch的实现比较简单&#xff0c;即先构建好平衡数据集train_set&#xff0c;然后构建trai…

Delphi中动态调用DLL的方法

Delphi中动态调用dll的方法如下&#xff1a; function CallFunc(dllname, funcname: string; const param: array of const): DWORD; varhLib: THandle;pFunc: Pointer;intSize: Integer; beginResult : 0;hLib : LoadLibrary(PChar(dllname));if hLib <> 0 then beginpF…

语音助手再次敲响隐私保护警钟

来源&#xff1a; 中国科学报智能手机内置的语音助手已成为人们生活中的亲密伙伴&#xff0c;大家习惯于让它完成报时、查询天气等日常任务甚至与它聊天解闷。然而&#xff0c;近期多家科技公司被曝光以智能语音助手录制用户谈话&#xff0c;再通过人工对语音做标注和反馈&…

大数据深度解析NLP文本摘要技术:定义、应用与PyTorch实战

文章目录 大数据深度解析NLP文本摘要技术&#xff1a;定义、应用与PyTorch实战1. 概述1.1 什么是文本摘要&#xff1f;1.2 为什么需要文本摘要&#xff1f; 2. 发展历程2.1 早期技术2.2 统计方法的崛起2.3 深度学习的应用2.4 文本摘要的演变趋势 3. 主要任务3.1 单文档摘要3.2 …

python+OpenCV图像处理(七)图像的形态学处理

图像的形态学处理 数学形态学&#xff08;Mathematical morphology&#xff09;是一门 建立在格论和拓扑学基础之上的图像分析学科&#xff0c;是数学形态学图像处理的基本理论。其基本的运算包括&#xff1a;腐蚀和膨胀、开运算和闭运算、骨架抽取、极限腐蚀、击中击不中变换、…

pandas取某一索引的数据

pandas.DataFrame.take(index) 返回给定位置索引中的元素。注意上面的index是元素的实际位置 举个例子&#xff1a; myList [[a, 10, 1.1],[b, 20, 2.2],[c, 30, 3.3],[d, 40, 4.4]] df1 pd.DataFrame(data myList) print(df1.take([2,3])) 输出&#xff1a; c 30 3.…

站立会议08

一、会议细节 时间   2014-4-27 21&#xff1a;10~21:40 地点   基教102 记录人   王岸城 二&#xff0c;会议记录 姓名今天你做了什么明天你要做什么今天遇到了什么问题王岸城记事本删除记事本修改无法使用数据库 苏月 实现登录和注册的连接 学习数据库 连接数据库信息…

【人工智能】机器人的未来发展:从工业自动化到知识自动化

来源&#xff1a;王飞跃博客【导读】智能时代的核心技术将是知识自动化&#xff0c;因此必须从一开始就加快、加强以软件形态为主的知识机器人的研发与应用&#xff0c;尽快形成软件和物理形态平行互动的新型机器人系统&#xff0c;并以此为突破口&#xff0c;引发下一代智能机…

python+OpenCV图像处理(八)边缘检测

边缘检测 边缘检测是图像处理和计算机视觉中的基本问题&#xff0c;边缘检测的目的是标识数字图像中亮度变化明显的点。图像属性中的显著变化通常反映了属性的重要事件和变化。边缘检测是特征提取中的一个研究领域。 图像边缘检测大幅度地减少了数据量&#xff0c;并且剔除了…

os.path.join拼接错误

csv_dir r"D:\test" print(os.path.join(csv_dir, r\test.csv)) 如上述代码所示&#xff0c;此时拼接后的路径为“D:\a.csv”&#xff0c;不符合预期&#xff0c;那是因为os.path.join第二个参数开头不能为斜杠和反斜杠&#xff0c;改为如下代码之后正确&#xff1…

bzoj 4551[Tjoi2016Heoi2016]树

这题可以用并查集做&#xff0c;一开始统计一下记录每个点被标记了几次&#xff0c;除了被标记过的点外&#xff0c;其他节点都与其父亲所在集合合并&#xff0c;然后倒着做&#xff0c;做的时候如果有节点标记次数变为了0&#xff0c;则将其与其父亲合并。 代码 1 #include<…

python+OpenCV图像处理(九)图像金字塔

图像金字塔 图像金字塔是图像多尺度表达的一种&#xff0c;是一种以多分辨率来解释图像的有效但概念简单的结构。图像金字塔最初用于机器视觉和图像压缩&#xff0c;一幅图像的金字塔是一系列以金字塔形状排列的分辨率逐步降低&#xff0c;且来源于同一张原始图的图像集合。其通…

ImportError: cannot import name ‘joblib‘

原因&#xff1a; 安装的Scikit-learn版本太高&#xff0c;我安装的版本是0.23.1 解决方法&#xff1a; 需要将Scikit-learn版本降到0.21以下 pip uninstall joblib scikit-learn sklearn pip install Scikit-learn0.20.4 或者直接安装joblib&#xff1a; pip install j…

3位物理学家获基础物理学特别突破奖

Peter van Nieuwenhuizen、Sergio Ferrara和Dan Freedman&#xff08;从左至右&#xff09;来源&#xff1a;中国科学报超引力理论是一个试图统一所有自然力的理论&#xff0c;在被提出40多年后&#xff0c;它是否能真实描述这个世界仍然悬而未决。尽管如此&#xff0c;该理论的…

python+OpenCV图像处理(十)霍夫变换简单图形检测

霍夫变换 霍夫变换&#xff08;Hough Transform&#xff09;是图像处理中从图像中识别几何形状的基本方法之一&#xff0c;应用很广泛&#xff0c;也有很多改进算法。主要用来从图像中分离出具有某种相同特征的几何形状&#xff08;如&#xff1a;直线、圆等&#xff09;。最基…