程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 一種c#深拷貝方法完勝java深拷貝(完成上的比較剖析)

一種c#深拷貝方法完勝java深拷貝(完成上的比較剖析)

編輯:C#入門知識

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

單位測試:

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved