In diesem Artikel werden die folgenden 4 Ausgaben erläutert
1. Java Clonable -Schnittstelle implementiert eine tiefe Kopie
2. Java -Serialisierung implementiert eine tiefe Kopie
3. Die schnellste Deep Copy Binärbibliothekskloning -Quellcodeanalyse
4. Vergleich der Geschwindigkeiten mehrerer Kopiermethoden
Ich werde in diesem Artikel nicht über das Konzept der tiefen Kopie sprechen. Implementierung einer tiefen Kopie in C ++. Überladen Sie im Allgemeinen den Zuordnungsoperator "=", um eine tiefe Kopie zwischen Objekten derselben Klasse zu implementieren. Daher ist es natürlich, dass wir in Java auch eine Kopierfunktion definieren können, um jede Eigenschaft des Objekts innerhalb der Funktion zuzuweisen. Diese Methode ist einfach und natürlich, aber es gibt ein fatales Problem: Wenn eines Tages ein neues Attribut erforderlich ist, für das die Klasse eine tiefe Kopie hinzugefügt wird, muss auch die entsprechende Kopierfunktion geändert werden. Diese Methode bringt große Unannehmlichkeiten für die Erweiterbarkeit der Klasse. So lösen wir dieses Problem, schauen wir uns die Implementierungsmethode der Kapitel 1, 2 und 3 und den Geschwindigkeitstest von Abschnitt 4 an.
1. Die klonbare Java -Schnittstelle implementiert Deep Copy <BR /> Auf diese Weise muss die Klasse die Colnable -Schnittstellenklonfunktion implementieren und Super.Clone in der Klonfunktion aufrufen. Diese tiefe Kopie der Methode bringt auch ein anderes Problem mit sich. Wenn es in der Klasse Objekte anderer Klassen als Eigenschaften gibt, müssen auch andere Klassen in der klonbaren Schnittstelle überladen und implementiert werden. Hier ist ein Beispiel. Im folgenden Beispiel enthält ComplexDo Simpledo -Objekte. Um die ComplexDo Deep Copy zu implementieren, müssen Sie zuerst die Klonschnittstelle von Simpledo implementieren:
öffentliche Klasse Simpledo implementiert klonbare, serialisierbare {private int x = 1; private Zeichenfolge S = "Simpledo"; @Override Protected Object Clone () löscht ClonenotsupportedException {Simpledo NewClass = (Simpledo) Super.clone (); NeueClass zurückgeben; }} öffentliche Klasse ComplexDo implementiert klonbare, serialisierbare {private int x = 1; private Zeichenfolge s = "komplex"; Private Ganzzahl a = 123; Private Ganzzahl B = 1234; Private Ganzzahl C = 1334455; private Zeichenfolge s2 = "hehehe"; private Zeichenfolge s3 = "hahaha"; private lange ID = 1233245L; private arrayList <Flunedo> l = new ArrayList <Flunedo> (); @Override public Object Clone () löst ClonenotsupportedException {ComplexDo NewClass = (ComplexDo) Super.clone () aus; newClass.l = new ArrayList <Flunedo> (); für (Simpledo Simple: this.l) {newClass.l.add ((Simpledo) Simple.clone ()); } return NewClass; }} Es ist zu beachten, dass viele Artikel sagen, dass der Zuordnungsbetreiber des String -Typs eine tiefe Kopie ist, aber tatsächlich sind diejenigen, die Zuordnungsbetreiber in Java verwenden, flache Kopien, aber warum müssen Artikel mit solch offensichtlichen Fehlern sagen, dass dies eine tiefe Kopie ist? Mein Verständnis ist, dass String- und Typattribute grundlegende Typen sind und die bereitgestellte Methode neue Objekte, solange die internen Datenänderungen entworfen werden. Daher wirkt sich eine String -Operation nicht auf den Speicher aus, auf den sie ursprünglich hingewiesen hat. Im Allgemeinen sind die Zuordnungsoperationen grundlegender Klassen wie String tiefe Kopien.
Aus diesem Grund muss bei Verwendung von String String-Spleißen ein neuer Speicher geöffnet werden. So viele Personen empfehlen, StringBuilder anstelle von String für das Spleißen zu verwenden, da StringBuilder nur einen größeren Speicher wieder aufzeigt, wenn der integrierte Char-Array-Bereich nicht ausreicht (für moderne JVMs, der Code wird abgestimmt, und String+String wird in ähnliche Anweisungen für StringBuilder.Append) optimiert. Um das Spleißen entgegenzunehmen, gibt es eine Substringfunktion in der Zeichenfolge. Ist das interne Zeichenarray der neuen Zeichenfolge bei der Substring -Funktion der ursprünglichen Zeichenfolge gleich? Das ist interessanter. Wenn Sie interessiert sind, können Sie die Implementierung von JDK1.6 und JKD1.7 vergleichen und überprüfen.
2. Java -Serialisierung implementiert eine tiefe Kopie
Das Prinzip dieser Methode besteht darin, die Java -Serialisierung zu verwenden, um ein Objekt in einen binären Bytestrom zu serialisieren und dann den Wert einem Objekt zu verdessten und zuzuweisen. Codebeispiel:
öffentliches Objekt SEEIRCOPY (Objekt 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); Objekt dest = in.readObject (); Rückkehrend; } catch (Ausnahme e) {// Erst einen Fehlerhandler return null; }} Natürlich können Sie auch JSON und andere serialisierte Bibliotheken verwenden, um die Serialisierung zu vervollständigen. Diese Methode vermeidet effektiv die erweiterbaren Mängel der Cloneabel -Schnittstelle. Eine Funktion kann im Grunde für alle Klassen geeignet sein. Der Nachteil ist, dass es sich um eine relative Speicherkopie handelt. Die Serialisierung erfordert zuerst, das Objekt in einen binären Bytestrom umzuwandeln und dann den binären Bytestrom in ein Stück Objektspeicher zu deserialisieren, das relativ langsam ist.
3. Die schnellste Deep Copy Binärbibliothekskloning -Quellcodeanalyse
Im Quellcode befindet sich die Kernverarbeitungslogik in der Klonerklasse.
Es gibt zwei rekursive Links:
In (1) vervollständigt Fastclone Objekte, die von der IfastClone -Schnittstellenklasse geerbt wurden, dh alle Kopien von Sammeloperationen;
In (2) vervollständigt das CloneObject den Prozess der Erfassung jeder Eigenschaft des normalen Objekts durch den Reflexionsmechanismus und zugewiesen dann die Eigenschaften des neu erzeugten Objekts unter Verwendung der Oblenese.
Diese Methode ist hoch erweiterbar. Sie können sich nicht nur auf den vorhandenen Code verlassen, um das Tiefenkopieren zu vervollständigen, sondern auch einige Klonen und Typen definieren, für die kein Klonen erforderlich ist, was sehr flexibel ist.
4. Vergleich der Geschwindigkeiten mehrerer Kopiermethoden
Die obigen drei Modi können verwendet werden, um das tiefgreifende Kopieren zu vervollständigen, und die am schnellsten Kopiermethode ist das, was uns wichtig ist.
Testen Sie zunächst den Code:
public void testcloneComplex () löst Clonenotsupportedexception aus {endgültig int copycount = 1; List <ComplexDo> complexDolist = new ArrayList <ComplexDo> (CopyCount * 3); endgültiger Komplexkomplex = neuer KomplexDo (); // Berechnung der Zwei-Seiten-Bibliothek lang start = system.currentTimemillis (); für (int i = 0; i <copycount; ++ i) {Final ComplexDo DeepClone = clner.Deepclone (komplex); ComplexDolist.Add (Deepclone); } Long End = System.currentTimemillis (); System.out.println ("DeepClone cost Time =" + (End-Start)); // Aufrufen der Klonfunktion, die von der klonbaren Schnittstelle start = system.currentTimemillis () implementiert wird; für (int i = 0; i <copycount; ++ i) {endgültiger Komplexdo interfaceClone = (complexDo) complex.clone (); complexDolist.add (interfaceClone); } end = system.currentTimemillis (); System.out.println ("interfaceClone cost time =" + (Endstart)); // Serialisierung und Deserialisierung erzeugen ein neues Objekt start = system.currentTimemillis (); für (int i = 0; i <copycount; ++ i) {endgültig komplexe Seirclone = SEIRCOPY (Komplex); ComplexDolist.Add (Seirclone); } end = system.currentTimemillis (); System.out.println ("Seirclone cost Time =" + (End-Start)); }Die Einheit der Laufergebnisse sind Millisekunden (diese Daten werden ignoriert und berechnen keine Java -Hotspots und möglichen GCs).
Aus dieser Tabelle können wir die Schlussfolgerung ziehen:
1. Das Kopieren der klonbaren Schnittstelle ist am schnellsten, da sie nur Speicherkopien beinhaltet. Wenn die beteiligten Attribute jedoch häufigere Objekte sind, ist es ein wenig mühsam zu schreiben.
2. Die Kopie der Serialisierung/Deserialisierung ist am langsamsten
3. Mit der Klonierungsbibliothek ist das Kopieren des Rekursions- und Reflexionsmechanismus langsamer als die klonbare Schnittstellenimplementierung, jedoch schneller als die Serialisierungsmethode.
Das Obige dreht sich alles um diesen Artikel, ich hoffe, es wird für das Lernen aller hilfreich sein.