一種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深拷貝(完成上的比較剖析)就是小編分享給年夜家的全體內容了,願望能給年夜家一個參考,也願望年夜家多多支撐。
單位測試: