一種c#深拷貝方法完勝java深拷貝(完成上的比較剖析)。本站提示廣大學習愛好者:(一種c#深拷貝方法完勝java深拷貝(完成上的比較剖析))文章只能為提供參考,不一定能成為您想要的結果。以下是一種c#深拷貝方法完勝java深拷貝(完成上的比較剖析)正文
樓主是一位asp.net攻城獅,比來常常跑java組客串協助開辟,所以比來對java的一些基本常識特殊上心。卻碰到須要將一個對象深拷貝出來做其他工作,而原對象堅持原有狀況的情形。(其實是不想本身new一個出來,然後對著一堆字段賦值......好吧,再此之前我沒有關懷能否項目框架有深拷貝的辦法),然後就想著用反射完成吧....接上去
是我本身的緣由,照樣真的不存在如許的純用反射完成的深拷貝方法....(c#是有純反射完成的)
但也不克不及算本身白忙活吧,也找到了其他完成深拷貝的方法(然則每種方法我都認為其實不是太公道,或許是由於c#的方法帶入了吧,最初貼出c#版本純反射完成深拷貝的代碼)
方法一:完成Cloneable接口,重寫clone辦法
實體類:一個輪胎類,一個車輛類,車輛中包括輪胎
/**輪胎類**/ public class Tire implements Cloneable { public String color; public int radius; public Tire(){} public Tire(String color, int radius) { this.color = color; this.radius = radius; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } } /**車輛類**/ public class Car implements Cloneable{ 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; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } }
@Test public void test() throws CloneNotSupportedException { Tire tire = new Tire("black",100); Car car = new Car("奔跑","white",tire); Car car_copy = (Car)car.clone(); System.out.println("car:"+car.hashCode()+" car.tire:"+car.tire.hashCode()); System.out.println("car_copy:"+car_copy.hashCode()+" car_copy.tire:"+car_copy.tire.hashCode()); car_copy.color = "blue"; System.out.println("car_copy:"+car_copy.color+" car:"+car.color); }
輸入成果:
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辦法:
@Override protected Object clone() throws CloneNotSupportedException { Car car = (Car)super.clone(); car.tire = (Tire)car.tire.clone(); return car; }
輸入成果:
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; } }
深拷貝辦法:
@SuppressWarnings("unchecked") public static Object deepClone(Object obj) { Object copyObj = null; ObjectOutputStream out = null; ObjectInputStream in = null; try { // 序列化 ByteArrayOutputStream bufferOut = new ByteArrayOutputStream(); out = new ObjectOutputStream(bufferOut); out.writeObject(obj); // 反序列化 ByteArrayInputStream bufferIn = new ByteArrayInputStream(bufferOut.toByteArray()); in = new ObjectInputStream(bufferIn); copyObj = in.readObject(); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); }finally{ try{ if(in != null){ in.close(); } if(out!=null){ out.close(); } }catch(IOException e){ throw new RuntimeException(e); } } return copyObj; }
單位測試:
@Test public void test() throws CloneNotSupportedException { Tire tire = new Tire("black",100); Car car = new Car("奔跑","white",tire); Car car_copy = (Car)deepClone(car); System.out.println("car:"+car.hashCode()+" car.tire:"+car.tire.hashCode()); System.out.println("car_copy:"+car_copy.hashCode()+" car_copy.tire:"+car_copy.tire.hashCode()); car_copy.color = "blue"; System.out.println("car_copy:"+car_copy.color+" car:"+car.color); }
輸入成果:
car:2019524978 car.tire:855703640 car_copy:1407965019 car_copy.tire:545768040 car_copy:blue car:white
從成果集中可以看出是深拷貝是准確的,然則每一個類照樣須要完成Serializable,似乎也不適合吧......
優化一下深拷貝辦法:將其換成泛型,如許拷貝出來就不須要強轉了(好吧,其實也沒比下面的辦法好到哪去...)
@SuppressWarnings("unchecked") public static <T> T deepClone(T obj) { T copyObj = null; ObjectOutputStream out = null; ObjectInputStream in = null; try { // 序列化 ByteArrayOutputStream bufferOut = new ByteArrayOutputStream(); out = new ObjectOutputStream(bufferOut); out.writeObject(obj); // 反序列化 ByteArrayInputStream bufferIn = new ByteArrayInputStream(bufferOut.toByteArray()); in = new ObjectInputStream(bufferIn); copyObj = (T)in.readObject(); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); }finally{ try{ if(in != null){ in.close(); } if(out!=null){ out.close(); } }catch(IOException e){ throw new RuntimeException(e); } } return copyObj; }
經由過程序列化與反序列化深拷貝還有更簡略的完成方法,就是須要導個包(拷貝的類也必需完成Serializable接口),固然,我曾經為你們預備好了 點擊->org.apache.commons.lang
深拷貝辦法:就一行代碼...
public Object deepClone(Object obj){ return org.apache.commons.lang.SerializationUtils.clone((Serializable)obj); }
好了,java的臨時就到這裡了,固然關於這兩種方法其實不是很滿足...
-------------------------------------------------
C#深拷貝 反射完成
上面辦法是c#的深拷貝,純反射完成,無需完成任何接口,哦對,須要實體類有個無參的結構辦法,簡略應用壯大,微軟年夜法好啊......有須要用到的同窗就拿去用吧,今朝經由一個幾百W的項目框架中考驗,真的壯大適用
/// <summary> /// 對象拷貝 /// </summary> /// <param name="obj">被復制對象</param> /// <returns>新對象</returns> private object CopyOjbect(object obj) { if (obj == null) { return null; } Object targetDeepCopyObj; Type targetType = obj.GetType(); //值類型 if (targetType.IsValueType == true) { targetDeepCopyObj = obj; } //援用類型 else { targetDeepCopyObj = System.Activator.CreateInstance(targetType); //創立援用對象 System.Reflection.MemberInfo[] memberCollection = obj.GetType().GetMembers(); foreach (System.Reflection.MemberInfo member in memberCollection) { //拷貝字段 if (member.MemberType == System.Reflection.MemberTypes.Field) { System.Reflection.FieldInfo field = (System.Reflection.FieldInfo)member; Object fieldValue = field.GetValue(obj); if (fieldValue is ICloneable) { field.SetValue(targetDeepCopyObj, (fieldValue as ICloneable).Clone()); } else { field.SetValue(targetDeepCopyObj, CopyOjbect(fieldValue)); } }//拷貝屬性 else if (member.MemberType == System.Reflection.MemberTypes.Property) { System.Reflection.PropertyInfo myProperty = (System.Reflection.PropertyInfo)member; MethodInfo info = myProperty.GetSetMethod(false); if (info != null) { try { object propertyValue = myProperty.GetValue(obj, null); if (propertyValue is ICloneable) { myProperty.SetValue(targetDeepCopyObj, (propertyValue as ICloneable).Clone(), null); } else { myProperty.SetValue(targetDeepCopyObj, CopyOjbect(propertyValue), null); } } catch (System.Exception ex) { } } } } } return targetDeepCopyObj; }
以上這篇一種c#深拷貝方法完勝java深拷貝(完成上的比較剖析)就是小編分享給年夜家的全體內容了,願望能給年夜家一個參考,也願望年夜家多多支撐。
單位測試: