This article discusses the following 4 issues
1. Java Cloneable interface implementation deep copy
2. Java serialization implementation of deep copy
3. The so-called fastest deep copy two square library cloning source analysis
4. Comparison of the speed of several copying modes
The concept of deep copy will not be mentioned in this article. Implement deep copy in C + + in general, the overloaded assignment operator "=" implements a deep copy between objects of the same class, so it is natural that in Java we can also define a copy function that assigns each property of the object to the function. This way is simple and natural, but there is a fatal problem: if one day in the class to add a need for deep copy of the attribute, then the corresponding copy function must also be modified, this approach to the scalability of the class has caused great inconvenience. How to solve this problem, and look at the next 1, 2, 3 chapters of Implementation and 4 section of the speed test.
1. Java cloneable interface implementation deep copy
In this way, a class is required to implement the Colneable interface clone function and Invoke Super.clone in the clone function. A deep copy of this approach also poses another problem, and if the class has objects of other classes as attributes, other classes also need to overload and implement the Cloneable interface. For example, in the following example, the Simpledo object is included in the Complexdo, and for the Complexdo deep copy to be implemented, the Simpledo clone interface needs to be implemented first:
public class Simpledo implements Cloneable, Serializable {private int x = 1;
Private String s = "Simpledo"; @Override protected Object Clone () throws Clonenotsupportedexception {Simpledo Newclass = (Simpledo) super.clone
();
return newclass;
} public class Complexdo implements Cloneable, Serializable {private int x = 1;
Private String s = "complex";
Private Integer a = 123;
Private Integer B = 1234;
Private Integer C = 1334455;
Private String s2 = "hehehe";
Private String s3 = "Hahahaha";
Private Long id = 1233245L;
Private arraylist<simpledo> L = new arraylist<simpledo> (); @Override public Object Clone () throws Clonenotsupportedexception {Complexdo Newclass = (complexdo) super.clone
();
NEWCLASS.L = new arraylist<simpledo> ();
for (Simpledo simple:this.l) {newclass.l.add (Simpledo) Simple.clone ());
return newclass;
}
}
Note that many articles say that the string type object assignment operator is a deep copy, but the fact that the assignment operator is used in Java is a shallow copy, but why is it so obvious that so many articles will have to say that this is a deep copy? My understanding is that string, type attributes are basic types, and that the method provided is designed to change the internal data to new objects. So a string operation does not affect the memory to which it was originally directed. Therefore, it is generally said that the assignment operations for base classes such as String are deep copies.
For this reason, there is a need to open new memory when using string concatenation, so many people suggest using StringBuilder instead of string for stitching, Because StringBuilder only reapply for larger memory when the built-in char array is not enough (for modern JVMs, the code is tuned, and string+string is optimized to resemble a stringbuilder.append directive). Cropping relative to stitching, there is a substring function in string, and when the SUBSTRING function is used, is the internal char array of the new string the same as the original string? This is more interesting and interesting to compare and see the JDK1.6 and JKD1.7 implementation.
2. Deep copy of Java serialization
This approach is based on Java serialization, serializing an object into a binary byte stream, and then deserializing the byte stream by assigning it to an object. code example:
public object Seircopy (object src) {
try {
Bytearrayoutputstream byteout = new Bytearrayoutputstream ();
ObjectOutputStream out = new ObjectOutputStream (byteout);
Out.writeobject (SRC);
Bytearrayinputstream Bytein = new Bytearrayinputstream (Byteout.tobytearray ());
ObjectInputStream in = new ObjectInputStream (Bytein);
Object dest = In.readobject ();
return dest;
} catch (Exception e) {
//do some error handler return
null;
}
}
Of course, you can also use a serialized library such as JSON to complete serialization, which effectively avoids the extensible disadvantages of the Cloneabel interface, A function can be basically applied to all classes. The disadvantage is that the relative memory copy, serialization needs to first convert the object into a binary byte stream, and then deserialize the binary stream into an object memory, relatively slow.
3. The so-called fastest deep copy two square library cloning source analysis
in the source code, the core processing logic is in the Cloner class,
Divided into two recursive links:
- (1) deepclone->cloneinternal->fastclone->cloneinternal
- (2) Deepclone->cloneinternal->cloneobject->cloneinternal
In (1) Fastclone completes the object which inherits from the Ifastcloner interface class, that is, the copy of some set operations;
In (2) Cloneobject completes each property of the normal object by means of a reflection mechanism, and assigns a value to the property that uses the Objenesis newly generated object.
This is a strong scalability, not only rely on their existing code to complete a deep copy, you can define some of the ways of cloning and do not need the type of cloning, flexibility.
4. Comparison of the speed of several copying modes
all of the above 3 modes can be done in deep copy, and that copy is the fastest way we care.
Test the code First:
public void Testclonecomplex () throws clonenotsupportedexception {Final int copycount = 1;
list<complexdo> complexdolist = new Arraylist<complexdo> (Copycount * 3);
Final Complexdo complex = new Complexdo ();
Call Jiffangku Long start = System.currenttimemillis ();
for (int i = 0; i < Copycount ++i) {final Complexdo Deepclone = Cloner.deepclone (complex);
Complexdolist.add (Deepclone);
Long end = System.currenttimemillis ();
System.out.println ("Deepclone cost time=" + (End-start));
Call the Cloneable interface implementation of the Clone function start = System.currenttimemillis ();
for (int i = 0; i < Copycount ++i) {final Complexdo Interfaceclone = (complexdo) complex.clone ();
Complexdolist.add (Interfaceclone);
End = System.currenttimemillis ();
System.out.println ("Interfaceclone cost time=" + (End-start));
Serialization and deserialization generation of new object start = System.currenttimemillis (); for (int i = 0; i < Copycount; ++i) {final ComPlexdo Seirclone = seircopy (complex);
Complexdolist.add (Seirclone);
End = System.currenttimemillis ();
System.out.println ("Seirclone cost time=" + (End-start));
}
The unit of the run result is milliseconds (this data ignores Java hotspots and possible GC).
From this table we can draw the conclusion that
1, the implementation of the Cloneable interface is the fastest copy, because he only involved in the memory copy, but if the attribute involved in the ordinary objects more time to write up trouble point
2, serialization/deserialization of the slowest copy
3, the use of cloning library, because the use of recursion and reflection mechanism relative to the Cloneable interface implementation of the copy is slower, but faster than the serialization mode.
The above is the entire content of this article, I hope to help you learn.