A C # deep copy way to win over Java deep copy (Implementation of comparative analysis) _c# Tutorial

Source: Internet
Author: User
Tags getcolor reflection serialization

Landlord is a asp.net siege lions, recently ran Java Group Guest to help develop, so recently some basic knowledge of Java special attention. There is a situation where you need to copy a object deeply to do something else, and the original object remains in its original state. (really do not want to new one out, and then to a pile of fields to assign value ...) Well, before that I didn't care if the project framework had a deep copy method, and then I wanted to do it with reflection .... Next

Is my own reason, or really there is no such a pure use of reflection implementation of the deep copy method .... (C # is implemented with pure reflection)

But also can not be counted on their own work, and found other ways to achieve deep copy (but each way I think it is not too reasonable, perhaps because of C # 's way into the bar, and finally posted a C # version of pure reflection to achieve deep copy of the code)

Way one: Implement Cloneable interface, rewrite Clone method

Entity class: A tyre class, a vehicle class, the vehicle contains the tyre

/** Tires Class **/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 ();
  /** Vehicle class **/public class Auto 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 ("car" +this.name+ "whistle ...");
  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");
    Car cars = new Car ("Mercedes", "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);
  }

Output results:

car:1223737555 car.tire:906199566
car_copy:542081238 car_copy.tire:906199566
car_copy:blue car:white

As a result, the car and the car_copy memory address is not the same, but Car.tire and Car_copy.tire memory address is the same, indicating that "Mercedes-Benz" has actually built another one, but the same tire (this case ...). hahaha), well, that is, just copy the tire reference, which can be said to be a deep copy of the incomplete (hashcode () value can be used as a memory address to understand), then how to complete, real deep copy?

To modify the Clone method in the car class:

@Override
  protected Object Clone () throws Clonenotsupportedexception {car car
    = (car) super.clone ();
    Car.tire = (tire) car.tire.clone ();
    return car;
  }

Output results:

car:1223737555 car.tire:906199566
car_copy:542081238 car_copy.tire:1133736492
car_copy:blue car:white

This is finally achieved, but this is not a good way to use the project, each need a deep copy of the class, to implement the Cloneable interface, and overwrite its Clone method, encountered in the reference to other classes when it is necessary to modify the Clone method, if you reference other classes, other classes to reference other classes? It's not good.

Mode two: through serialization and deserialization implementation (implementation of the Serializable interface)

Entity classes: Similar to the first method, replace the Clone method with the implementation of the Serializable interface

/** Tyre class **/@SuppressWarnings ("Serial") public class tire implements java.io.Serializable {Publ
  IC String color;
  public int radius;
    Public tire () {} public tire (String color, int radius) {this.color = color;
  This.radius = radius;
  /** Vehicle class **/@SuppressWarnings ("Serial") public class Auto 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 ("car" +this.name+ "whistle ...");
  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; }
}

Deep Copy method:

@SuppressWarnings ("unchecked") public
  static Object Deepclone (Object obj)
  {
    object copyobj = null;
    ObjectOutputStream out = null;
    ObjectInputStream in = null;
    try {
      //serialization
      Bytearrayoutputstream bufferout = new Bytearrayoutputstream ();
      out = new ObjectOutputStream (bufferout);

      Out.writeobject (obj);

      Deserialization
      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;
  }

Unit test:

@Test public
  void Test () throws Clonenotsupportedexception {
    Tire tire = new Tire ("Black");
    Car cars = new Car ("Mercedes", "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);
  }

Output results:

car:2019524978 car.tire:855703640
car_copy:1407965019 car_copy.tire:545768040
car_copy:blue car:white

It can be seen from the result set that the deep copy is correct, but each class still needs to implement serializable, as if not appropriate ...

Optimize the deep copy method: replace it with a generic, so that the copy out of the need for a strong turn (well, in fact, there is no better than the above method to go ...) )

 @SuppressWarnings ("unchecked") public static <T> T Deepclone (t obj) {t
    Copyobj = null;
    ObjectOutputStream out = null;
    ObjectInputStream in = null;
      try {//serialization Bytearrayoutputstream Bufferout = new Bytearrayoutputstream ();

      out = new ObjectOutputStream (bufferout);

      Out.writeobject (obj);
      Deserialization 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; }

A simpler way to implement a deep copy of serialization and deserialization is to lead a package (the copy class must also implement the Serializable interface), and of course, I've got you ready to click->org.apache.commons.lang

Deep Copy method: Just one line of code ...

public object Deepclone (object obj) {return
     org.apache.commons.lang.SerializationUtils.clone (Serializable) obj );
   }

OK, Java is here for the time being, of course, for these two ways is not very satisfied ...

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

C # Deep Copy reflection implementation

The following method is a deep copy of C #, pure reflection implementation, no need to implement any interface, oh yes, need entity classes have a parameterless construction method, simple to use strong, Microsoft Dafa good ah ... Need to use the students to use it, now after a hundreds of-W Project framework test, really powerful practical

<summary>///Object Copy///</summary>///<param name= "obj" > Replicated object </param>///
      ;returns> New Object </returns> Private Object Copyojbect (object obj) {if (obj = = null) {return null;
      } Object Targetdeepcopyobj; Type targettype = obj.
      GetType ();
      Value type if (Targettype.isvaluetype = = true) {targetdeepcopyobj = obj;  }//reference type else {targetdeepcopyobj = System.Activator.CreateInstance (targettype); Create reference object system.reflection.memberinfo[] membercollection = obj. GetType ().

        GetMembers (); foreach (System.Reflection.MemberInfo member in membercollection) {//Copy field if (member. MemberType = = System.Reflection.MemberTypes.Field) {System.Reflection.FieldInfo Field = (system.ref Lection.
            FieldInfo) member; Object fieldvalue = field.
            GetValue (obj);
        if (Fieldvalue is ICloneable) {      Field. SetValue (Targetdeepcopyobj, fieldvalue as ICloneable).
            Clone ()); } else {field.
            SetValue (Targetdeepcopyobj, Copyojbect (Fieldvalue)); }//Copy attribute else if (member. MemberType = = System.Reflection.MemberTypes.Property) {System.Reflection.PropertyInfo MyProperty = (system.re Flection.

            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 Iclone ABLE).
                Clone (), NULL);
                else {myproperty.setvalue (targetdeepcopyobj, Copyojbect (PropertyValue), null);
 The catch (System.Exception ex) {}}}       } return targetdeepcopyobj; }

Above this one kind of C # deep copy way to win the Java deep copy (realizes the contrast analysis) is the small series to share to everybody's content, hoped can give everybody a reference, also hoped that everybody supports the cloud habitat community.

Unit test:

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.