内容简介:java中复制对象通过反射或序列化
在使用缓存读取数据后修改发现缓存被修改。于是找了下复制对象的方法。
关于对象克隆
按我的理解,对象是包含引用+数据。通常变量复制都是将引用传递过去。比如:
1 Person p1 = new Person(); 2 Person p2 = p1;
这两句话,创建两个引用p1,p2,但指向共同的内存大堆数据。修改任何一个,另一个的数据也将修改。
直接引用传递测试用例:
1.实体类:
View Code
2.测试类
1 package com.test.java;
2
3 /**
4 * Created by Administrator on 2015/11/26.
5 * 测试对象引用
6 */
7 public class TestRef {
8
9 public static void main(String[] args) {
10 Country country = new Country(1,"china");
11 Person person = new Person(country,1,"test");
12
13 Country country1 = country;
14 Person person1 = person;
15
16 System.out.println("创建国家 :"+country);
17 System.out.println("引用传递国家 :"+country1);
18 System.out.println("创建人 :"+person);
19 System.out.println("引用传递创建人:"+person1);
20
21 }
22
23 }
3.打印结果:
4.分析:
通过hashcode可以证明,数据实体的地址是相同的。关于基本类型和引用类型的内存关系,可以参考 这篇 。
同样,通过实现clone接口,重载clone方法,然后调用person.clone()来复制对象的浅克隆是一样。参考 这篇 。
当然,采用深度克隆的话就可以生成两个完全不同的对象。
然而,我们创建的实体通常是不会实现和覆盖clone的,这种办法只能提前写好对应的类才可以实现。因此,不推荐使用。
那么,我们可以通过反射或者序列化来实现。
关于序列化
参考 博客 , Java序列化 是指把 Java 对象转换为字节序列的过程;而 Java反序列化 是指把字节序列恢复为Java对象的过程。字节码可以存储,无状态,而对象在内存中开辟空间,有地址。
由此,可以把对象序列化后反序列化。相当于破碎重组。
前提是:实体类需要实现序列化接口
1.序列化实现对象复制
1 // 用序列化与反序列化实现深克隆
2 public static Object cloneBySer(Object baseObj) {
3 Object o = null;
4 try {
5 ByteArrayOutputStream baos = new ByteArrayOutputStream();
6 ObjectOutputStream oos = new ObjectOutputStream(baos);
7 oos.writeObject(baseObj);
8 oos.close();
9 ByteArrayInputStream bais = new ByteArrayInputStream(baos
10 .toByteArray());
11 ObjectInputStream ois = new ObjectInputStream(bais);
12 o = ois.readObject();
13 ois.close();
14 } catch (IOException e) {
15 e.printStackTrace();
16 } catch (ClassNotFoundException e) {
17 e.printStackTrace();
18 }
19 return o;
20 }
2.测试用例:
1 public static void main(String[] args) {
2 Country country = new Country(1,"china");
3 Person person = new Person(country,1,"test");
4 //引用传递
5 Country country1 = country;
6 Person person1 = person;
7 //序列化和反序列化
8 Object person2 = ObjectCopy.cloneBySer(person);
9 Object country2 = ObjectCopy.cloneBySer(country);
10
11 // person.setAge(12);
12
13 System.out.println("创建国家 :"+country);
14 System.out.println("引用传递国家 :"+country1);
15 System.out.println("序列化复制国家 :"+country2);
16 System.out.println("创建人 :"+person);
17 System.out.println("引用传递人:"+person1);
18 System.out.println("序列化复制人:"+person2);
19
20 }
3.控制台打印:
4.分析
序列化完全实现了对象拷贝。要求:对象都实现序列化,对象hashcode和equals方法默认或者包含全部信息。
通过反射
反射可以复制一个对象的属性,从而实现对象拷贝
反射代码:
1 /**
2 * COPY对象(毛病还是很多的。。)
3 *对基本类型的过滤
4 * @author Lv9
5 * @since 2010.03.09
6 * baseObject 要拷贝的对象
7 * noCopyClassNames 不深度拷贝的对象属性
8 */
9 public static Object coloneByRef(Object baseObject,
10 String... noCopyClassNames) throws Exception {
11 Object copyObject = baseObject.getClass().newInstance();
12 Field[] fields = baseObject.getClass().getDeclaredFields();
13 for (Field field : fields) {
14 field.setAccessible(true);
15 if (checkClassType(field.getType().getName(), noCopyClassNames)) {
16 field.set(copyObject, field.get(baseObject));
17 } else {
18 field.set(copyObject, coloneByRef(field.get(baseObject),
19 noCopyClassNames));
20 }
21 }
22 return copyObject;
23 }
24
25 public static boolean checkClassType(String className,
26 String[] noCopyClassNames) {
27 for (String noCopyClassName : noCopyClassNames) {
28 if (className.equals(noCopyClassName)) {
29 return true;
30 }
31 }
32 return false;
33 }
一个失败的用例:
反射用的不太会
View Code
本文转自Ryan.Miao博客园博客,原文链接:http://www.cnblogs.com/woshimrf/p/4998885.html,如需转载请自行联系原作者
以上所述就是小编给大家介绍的《java中复制对象通过反射或序列化》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Introduction to the Design and Analysis of Algorithms
Anany Levitin / Addison Wesley / 2011-10-10 / USD 117.00
Based on a new classification of algorithm design techniques and a clear delineation of analysis methods, Introduction to the Design and Analysis of Algorithms presents the subject in a coherent a......一起来看看 《Introduction to the Design and Analysis of Algorithms》 这本书的介绍吧!