是我自己的原因,还是真的不存在这样的纯用反射实现的深拷贝方式....(c#是有纯反射实现的)
但也不能算自己白忙活吧,也找到了其他实现深拷贝的方式(但是每种方式我都觉得并不是太合理,也许是因为c#的方式带入了吧,最后贴出c#版本纯反射实现深拷贝的代码)
方式一:实现Cloneable接口,重写clone方法
实体类:一个轮胎类,一个车辆类,车辆中包含轮胎
1
2 public class Tire implements Cloneable {
3 public String color;
4 public int radius;
5 public Tire(){}
6 public Tire(String color, int radius) {
7 this.color = color;
8 this.radius = radius;
9 }
10
11 @Override
12 protected Object clone() throws CloneNotSupportedException {
13 return super.clone();
14 }
15 }
16
17 public class Car implements Cloneable{
18 public String name;
19 public String color;
20 public Tire tire;
21 public Car() {}
22 public Car(String name, String color, Tire tire) {
23 this.name = name;
24 this.color = color;
25 this.tire = tire;
26 }
27 public void whistle(){
28 System.out.println("汽车"+this.name+" 鸣笛...");
29 }
30 public String getName() {
31 return name;
32 }
33 public void setName(String name) {
34 this.name = name;
35 }
36 public String getColor() {
37 return color;
38 }
39 public void setColor(String color) {
40 this.color = color;
41 }
42 public Tire getTire() {
43 return tire;
44 }
45 public void setTire(Tire tire) {
46 this.tire = tire;
47 }
48 @Override
49 protected Object clone() throws CloneNotSupportedException {
50 return super.clone();
51 }
52 }
单元测试:
1 @Test
2 public void test() throws CloneNotSupportedException {
3 Tire tire = new Tire("black",100);
4 Car car = new Car("奔驰","white",tire);
5 Car car_copy = (Car)car.clone();
6 System.out.println("car:"+car.hashCode()+" car.tire:"+car.tire.hashCode());
7 System.out.println("car_copy:"+car_copy.hashCode()+" car_copy.tire:"+car_copy.tire.hashCode());
8 car_copy.color = "blue";
9 System.out.println("car_copy:"+car_copy.color+" car:"+car.color);
10 }
输出结果:
car:1223737555 car.tire:906199566
car_copy:542081238 car_copy.tire:906199566
car_copy:blue car:white
从结果可以的之,car与car_copy的内存地址并不一致,但car.tire与car_copy.tire的内存地址却是一致的,说明“奔驰”车确实又造出了一辆,但却公用同一幅轮胎(这种情形....哈哈哈),好吧,也就是只复制了tire的引用,这可以说是深拷贝的不彻底 (hashCode()的值可以当作是内存地址来理解),那么要怎样才能彻底,真正的深拷贝?
修改Car类中的clone方法:
1 @Override
2 protected Object clone() throws CloneNotSupportedException {
3 Car car = (Car)super.clone();
4 car.tire = (Tire)car.tire.clone();
5 return car;
6 }
输出结果:
car:1223737555 car.tire:906199566
car_copy:542081238 car_copy.tire:1133736492
car_copy:blue car:white
这样最终实现了,但这种方式用到项目中并不是很合适吧,每个需要深拷贝的类,都要实现Cloneable接口,并覆盖其clone方法,遇到引用其他类时候更是需要修改clone方法,要是引用其他类,其他类再引用其他类呢?这不好吧......
方式二:通过序列化与反序列化实现(实现Serializable接口)
实体类:与第一种方式类似,换成实现Serializable接口,去掉clone方法
@SuppressWarnings("serial")
public class Tire implements java.io.Serializable {
public String color;
public int radius;
public Tire(){}
public Tire(String color, int radius) {
this.color = color;
this.radius = radius;
}
}
@SuppressWarnings("serial")
public class Car implements java.io.Serializable{
public String name;
public String color;
public Tire tire;
public Car() {}
public Car(String name, String color, Tire tire) {
this.name = name;
this.color = color;
this.tire = tire;
}
public void whistle(){
System.out.println("汽车"+this.name+" 鸣笛...");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public Tire getTire() {
return tire;
}
public void setTire(Tire tire) {
this.tire = tire;
}
}
深拷贝方法:
1 @SuppressWarnings("unchecked")
2 public static Object deepClone(Object obj)
3 {
4 Object copyObj = null;
5 ObjectOutputStream out = null;
6 ObjectInputStream in = null;
7 try {
8 // 序列化
9 ByteArrayOutputStream bufferOut = new ByteArrayOutputStream();
10 out = new ObjectOutputStream(bufferOut);
11
12 out.writeObject(obj);
13
14 // 反序列化
15 ByteArrayInputStream bufferIn = new ByteArrayInputStream(bufferOut.toByteArray());
16 in = new ObjectInputStream(bufferIn);
17 copyObj = in.readObject();
18 } catch (Exception e) {
19 e.printStackTrace();
20 throw new RuntimeException(e);
21 }finally{
22 try{
23 if(in != null){
24 in.close();
25 }
26 if(out!=null){
27 out.close();
28 }
29 }catch(IOException e){
30 throw new RuntimeException(e);
31 }
32 }
33 return copyObj;
34 }
单元测试:
1 @Test
2 public void test() throws CloneNotSupportedException {
3 Tire tire = new Tire("black",100);
4 Car car = new Car("奔驰","white",tire);
5 Car car_copy = (Car)deepClone(car);
6 System.out.println("car:"+car.hashCode()+" car.tire:"+car.tire.hashCode());
7 System.out.println("car_copy:"+car_copy.hashCode()+" car_copy.tire:"+car_copy.tire.hashCode());
8 car_copy.color = "blue";
9 System.out.println("car_copy:"+car_copy.color+" car:"+car.color);
10 }
输出结果:
car:2019524978 car.tire:855703640
car_copy:1407965019 car_copy.tire:545768040
car_copy:blue car:white
从结果集中可以看出是深拷贝是正确的,但是每个类还是需要实现Serializable,好像也不合适吧......
优化一下深拷贝方法:将其换成泛型,这样拷贝出来就不需要强转了(好吧,其实也没比上面的方法好到哪去...)
1 @SuppressWarnings("unchecked")
2 public static T deepClone(T obj)
3 {
4 T copyObj = null;
5 ObjectOutputStream out = null;
6 ObjectInputStream in = null;
7 try {
8 // 序列化
9 ByteArrayOutputStream bufferOut = new ByteArrayOutputStream();
10 out = new ObjectOutputStream(bufferOut);
11
12 out.writeObject(obj);
13
14 // 反序列化
15 ByteArrayInputStream bufferIn = new ByteArrayInputStream(bufferOut.toByteArray());
16 in = new ObjectInputStream(bufferIn);
17 copyObj = (T)in.readObject();
18 } catch (Exception e) {
19 e.printStackTrace();
20 throw new RuntimeException(e);
21 }finally{
22 try{
23 if(in != null){
24 in.close();
25 }
26 if(out!=null){
27 out.close();
28 }
29 }catch(IOException e){
30 throw new RuntimeException(e);
31 }
32 }
33 return copyObj;
34 }
通过序列化与反序列化深拷贝还有更简单的实现方式,就是需要导个包(拷贝的类也必须实现Serializable接口),当然,我已经为你们准备好了 点击->
深拷贝方法:就一行代码...
1 public Object deepClone(Object obj){
2 return org.apache.commons.lang.SerializationUtils.clone((Serializable)obj);
3 }
好了,java的暂时就到这里了,当然对于这两种方式并不是很满意...
-------------------------------------------------
C#深拷贝 反射实现
下面方法是c#的深拷贝,纯反射实现,无需实现任何接口,哦对,需要实体类有个无参的构造方法,简单使用强大,微软大法好啊......有需要用到的同学就拿去用吧,目前经过一个几百W的项目框架中考验,真的强大实用
1 ///
2 /// 对象拷贝
3 ///
4 /// 被复制对象
5 /// 新对象
6 private object CopyOjbect(object obj) {
7 if (obj == null) {
8 return null;
9 }
10 Object targetDeepCopyObj;
11 Type targetType = obj.GetType();
12 //值类型
13 if (targetType.IsValueType == true) {
14 targetDeepCopyObj = obj;
15 }
16 //引用类型
17 else {
18 targetDeepCopyObj = System.Activator.CreateInstance(targetType); //创建引用对象
19 System.Reflection.MemberInfo[] memberCollection = obj.GetType().GetMembers();
20
21 foreach (System.Reflection.MemberInfo member in memberCollection) {
22 //拷贝字段
23 if (member.MemberType == System.Reflection.MemberTypes.Field)
24 {
25 System.Reflection.FieldInfo field = (System.Reflection.FieldInfo)member;
26 Object fieldValue = field.GetValue(obj);
27 if (fieldValue is ICloneable)
28 {
29 field.SetValue(targetDeepCopyObj, (fieldValue as ICloneable).Clone());
30 }
31 else
32 {
33 field.SetValue(targetDeepCopyObj, CopyOjbect(fieldValue));
34 }
35
36 }//拷贝属性
37 else if (member.MemberType == System.Reflection.MemberTypes.Property) {
38 System.Reflection.PropertyInfo myProperty = (System.Reflection.PropertyInfo)member;
39
40 MethodInfo info = myProperty.GetSetMethod(false);
41 if (info != null) {
42 try {
43 object propertyValue = myProperty.GetValue(obj, null);
44 if (propertyValue is ICloneable) {
45 myProperty.SetValue(targetDeepCopyObj, (propertyValue as ICloneable).Clone(), null);
46 }
47 else {
48 myProperty.SetValue(targetDeepCopyObj, CopyOjbect(propertyValue), null);
49 }
50 }
51 catch (System.Exception ex) {
52
53 }
54 }
55 }
56 }
57 }
58 return targetDeepCopyObj;
59 }
public static T DeepClone(T obj)
{
using (var ms = new MemoryStream())
{
var formatter = new BinaryFormatter();
formatter.Serialize(ms, obj);
ms.Position = 0;
return (T) formatter.Deserialize(ms);
}
}