天天看点

java 反射实现深拷贝_一种c#深拷贝方式完胜java深拷贝(实现上的对比)

java 反射实现深拷贝_一种c#深拷贝方式完胜java深拷贝(实现上的对比)

是我自己的原因,还是真的不存在这样的纯用反射实现的深拷贝方式....(c#是有纯反射实现的)

但也不能算自己白忙活吧,也找到了其他实现深拷贝的方式(但是每种方式我都觉得并不是太合理,也许是因为c#的方式带入了吧,最后贴出c#版本纯反射实现深拷贝的代码)

方式一:实现Cloneable接口,重写clone方法

实体类:一个轮胎类,一个车辆类,车辆中包含轮胎

java 反射实现深拷贝_一种c#深拷贝方式完胜java深拷贝(实现上的对比)

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 }

java 反射实现深拷贝_一种c#深拷贝方式完胜java深拷贝(实现上的对比)

单元测试:

java 反射实现深拷贝_一种c#深拷贝方式完胜java深拷贝(实现上的对比)

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 }

java 反射实现深拷贝_一种c#深拷贝方式完胜java深拷贝(实现上的对比)

输出结果:

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方法:

java 反射实现深拷贝_一种c#深拷贝方式完胜java深拷贝(实现上的对比)

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 }

java 反射实现深拷贝_一种c#深拷贝方式完胜java深拷贝(实现上的对比)

输出结果:

car:1223737555 car.tire:906199566

car_copy:542081238 car_copy.tire:1133736492

car_copy:blue car:white

这样最终实现了,但这种方式用到项目中并不是很合适吧,每个需要深拷贝的类,都要实现Cloneable接口,并覆盖其clone方法,遇到引用其他类时候更是需要修改clone方法,要是引用其他类,其他类再引用其他类呢?这不好吧......

方式二:通过序列化与反序列化实现(实现Serializable接口)

实体类:与第一种方式类似,换成实现Serializable接口,去掉clone方法

java 反射实现深拷贝_一种c#深拷贝方式完胜java深拷贝(实现上的对比)

@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;

}

}

java 反射实现深拷贝_一种c#深拷贝方式完胜java深拷贝(实现上的对比)

深拷贝方法:

java 反射实现深拷贝_一种c#深拷贝方式完胜java深拷贝(实现上的对比)

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 }

java 反射实现深拷贝_一种c#深拷贝方式完胜java深拷贝(实现上的对比)

单元测试:

java 反射实现深拷贝_一种c#深拷贝方式完胜java深拷贝(实现上的对比)

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 }

java 反射实现深拷贝_一种c#深拷贝方式完胜java深拷贝(实现上的对比)

输出结果:

car:2019524978 car.tire:855703640

car_copy:1407965019 car_copy.tire:545768040

car_copy:blue car:white

从结果集中可以看出是深拷贝是正确的,但是每个类还是需要实现Serializable,好像也不合适吧......

优化一下深拷贝方法:将其换成泛型,这样拷贝出来就不需要强转了(好吧,其实也没比上面的方法好到哪去...)

java 反射实现深拷贝_一种c#深拷贝方式完胜java深拷贝(实现上的对比)

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 }

java 反射实现深拷贝_一种c#深拷贝方式完胜java深拷贝(实现上的对比)

通过序列化与反序列化深拷贝还有更简单的实现方式,就是需要导个包(拷贝的类也必须实现Serializable接口),当然,我已经为你们准备好了 点击->

深拷贝方法:就一行代码...

1 public Object deepClone(Object obj){

2 return org.apache.commons.lang.SerializationUtils.clone((Serializable)obj);

3 }

好了,java的暂时就到这里了,当然对于这两种方式并不是很满意...

-------------------------------------------------

C#深拷贝 反射实现

下面方法是c#的深拷贝,纯反射实现,无需实现任何接口,哦对,需要实体类有个无参的构造方法,简单使用强大,微软大法好啊......有需要用到的同学就拿去用吧,目前经过一个几百W的项目框架中考验,真的强大实用

java 反射实现深拷贝_一种c#深拷贝方式完胜java深拷贝(实现上的对比)

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);

}

}