[改善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
[改善Java代码] 推荐使用序列化实现对象的拷贝相关推荐
- java 编码实现内存拷贝_java提高篇(六)-----使用序列化实现对象的拷贝
我们知道在Java中存在这个接口Cloneable,实现该接口的类都会具备被拷贝的能力,同时拷贝是在内存中进行,在性能方面比我们直接通过new生成对象来的快,特别是在大对象的生成上,使得性能的提升非常 ...
- 改善Java代码有哪些方法?
前言 Java是一门优秀的面向对象的编程语言,针对遇到同样的一个问题会有很多中解法哪种实现方法是最好的呢,还需要不断的探究JDK的底层原理.我会例出Java改善的建议哦,希望大家可以在平时开发工作去使 ...
- java 代码解析工具_改善 Java 代码质量的工具与方法
原标题:改善 Java 代码质量的工具与方法 我们可能见过上面的有关代码质量的图片,究竟如何衡量一段代码好坏? 代码质量是什么?为什么它很重要? 作家通过他的著作来讲述了一个清晰的.令人信服的故事.他 ...
- 使用序列化实现对象的拷贝(转载)
文章出处:http://www.cnblogs.com/chenssy/p/3382979.html 实现Cloneable接口:实现该接口的类都会具备被拷贝的能力,同时拷贝是在内存中进行,在性能方面 ...
- java 防止拷贝_[改善Java代码]避免对象的浅拷贝
建议43: 避免对象的浅拷贝 我们知道一个类实现了Cloneable接口就表示它具备了被拷贝的能力,如果再覆写clone()方法就会完全具备拷贝能力.拷贝是在内存中进行的,所以在性能方面比直接通过ne ...
- [改善Java代码]养成良好习惯,显式声明UID
建议11: 养成良好习惯,显式声明UID 我们编写一个实现了Serializable接口(序列化标志接口)的类, Eclipse马上就会给一个黄色警告:需要增加一个Serial Version ID. ...
- [改善Java代码]非稳定排序推荐使用List
我们知道Set与List的最大区别就是Set中的元素不可以重复(这个重复指的equals方法的返回值相等),其他方面则没有太大的区别了,在Set的实现类中有一个比较常用的类需要了解一下:TreeSet ...
- java 不可修改的集合对象_[改善Java代码]asList方法产生的List对象不可更改
上一个建议之处了asList方法在转换基本类型数组时候存在的问题,在看下asList方法返回的列表有何特殊的地方.看代码: importjava.util.Arrays;importjava.util ...
- [改善Java代码]不推荐使用binarySearch对列表进行检索
对一个列表进行检索时,我们使用的最多的是indexOf方法,它简单好用,而且也不会出错,虽然它只能检索到第一个符合条件的值,但是我们可以生成子列表后再检索.这样也就可以查找到所有符合条件的值了. Co ...
最新文章
- [c#基础]关于try...catch最常见的笔试题
- 聊聊、Zookeeper 客户端 Curator
- LeaFlet学习之结合turf.js生成简单的等值线demo
- [iPhoneアプリ]iEscaper2攻略その6|龍の水晶
- 浅析Java内存模型
- C/C++只做经典编程语言
- IOS的一些文件操作。(沙箱) 在Documents目录下创建文件
- python模块名不规范如何导入_如何强制Python的“导入”将名称视为模块,而不是函数?...
- 【iOS-Cocos2d游戏开发之六】对触屏事件追加讲解,解决无法触发ccTouchMoved事件[重要!]...
- 带货造假,买完不能换货?李佳琦、汪涵、李雪琴直播被中消协点名后这样回应...
- [转载] pandas dataframe 提取行和列
- 按键精灵定位坐标循环_按键精灵的控制命令居然恐怖到了这种程度
- 一个未完毕创业项目的思考——创业杂记
- Python-15 函数:我的地盘听我的
- ultrascale和arm区别_ZYNQ UltraScale+ MPSoc FPGA初学笔记
- 守护安全|AIRIOT城市天然气综合管理解决方案
- 结构化数据和非结构化数据的分析
- 数电实验三 数据选择器及其应用 任务一:用74151芯片采用降维的方法实现F=ABC+ABD+ACD+BCD; 任务二:用74151芯片采用降维方式实现F=BCD反+BC反+A反D;
- d3带箭头和点击事件的力导向关系图
- 数字电路实验 07 - | 计数器及其应用
热门文章
- pandas 读表格_pandas电子表格的读取(pandas中的read_excel)
- Vue项目中 css样式的作用域(深度作用选择器)
- python web开发 jQuery基础
- 天池 在线编程 输入流
- LeetCode 1562. 查找大小为 M 的最新分组
- LeetCode MySQL 1336. 每次访问的交易次数
- LintCode 1210. 升序子序列(DFS)
- LeetCode 937. 重新排列日志文件(自定义排序)
- python使方法执行10次_Python提升程序性能的七个手段
- python中_str_使用方法