java中复制对象通过反射或序列化

栏目: Java · 发布时间: 7年前

内容简介: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.打印结果:

java中复制对象通过反射或序列化

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.控制台打印:

java中复制对象通过反射或序列化

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中复制对象通过反射或序列化》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

How to Solve It

How to Solve It

Zbigniew Michalewicz、David B. Fogel / Springer / 2004-03-01 / USD 59.95

This book is the only source that provides comprehensive, current, and detailed information on problem solving using modern heuristics. It covers classic methods of optimization, including dynamic pro......一起来看看 《How to Solve It》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

在线进制转换器
在线进制转换器

各进制数互转换器

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具