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: