Alle Ansätze zum Kopieren von Objekten in Java weisen schwerwiegende Mängel auf:
Klon
- Die clone () -Methode ist geschützt, sodass Sie sie nur dann direkt aufrufen können, wenn die betreffende Klasse sie mit einer öffentlichen Methode überschreibt.
- clone () ruft den Konstruktor nicht auf. Jeder Konstruktor. Es wird Speicher zuweisen, das interne
class
Feld zuweisen (über das Sie lesen können getClass()
) und die Felder des Originals kopieren.
Weitere Probleme mit clone () finden Sie in Punkt 11 von Joshua Blochs Buch " Effective Java, Second Edition ".
Serialisieren
Serialisieren ist noch schlimmer; es hat viele der Mängel von clone()
und noch einige mehr. Joshua hat ein ganzes Kapitel mit vier Punkten allein für dieses Thema.
Meine Lösung
Meine Lösung besteht darin, meinen Projekten eine neue Oberfläche hinzuzufügen:
public interface Copyable<T> {
T copy ();
T createForCopy ();
void copyTo (T dest);
}
Der Code sieht folgendermaßen aus:
class Demo implements Copyable<Demo> {
public Demo copy () {
Demo copy = createForCopy ();
copyTo (copy);
return copy;
}
public Demo createForCopy () {
return new Demo ();
}
public void copyTo (Demo dest)
super.copyTo (dest);
...copy fields of Demo here...
}
}
Leider muss ich diesen Code in alle meine Objekte kopieren, aber es ist immer der gleiche Code, sodass ich eine Eclipse-Editor-Vorlage verwenden kann. Vorteile:
- Ich kann entscheiden, welcher Konstruktor aufgerufen werden soll und wie welches Feld initialisiert werden soll.
- Die Initialisierung erfolgt in einer deterministischen Reihenfolge (Stammklasse zu Instanzklasse).
- Ich kann vorhandene Objekte wiederverwenden und überschreiben
- Geben Sie safe ein
- Singletons bleiben Singletons
Für Standard-Java-Typen (wie Sammlungen usw.) verwende ich eine Dienstprogrammklasse, die diese kopieren kann. Die Methoden haben Flags und Callbacks, sodass ich steuern kann, wie tief eine Kopie sein soll.