Frage
Ich war für einige Tutorials über Java Cloneable
zu erklären, aber haben keine gute Links erhalten, und Stack-Überlauf wird immer sowieso mehr offensichtliche Wahl.
Ich möchte Folgendes wissen:
-
Cloneable
bedeutet wir einen Klon oder um eine Kopie der Objekte haben kann, durch die Umsetzung derCloneable
Schnittstelle. Was sind die Vorteile und Nachteile, das zu tun? - Wie geschieht das rekursive Klonen, wenn das Objekt a Verbundobjekt?
Lösung
Das erste, was Sie über Cloneable
wissen sollten ist, -. Nicht verwenden
Es ist sehr schwer zu implementieren mit Cloneable
Recht des Klonen und die Mühe nicht wert.
Statt dessen Verwendung einige andere Optionen, wie Apache-Commons SerializationUtils
(deep-Klon) oder BeanUtils
(shallow-Klon) oder einfach eine Kopie-Konstruktor verwenden.
hier sehen für die Ansichten von Josh Bloch etwa mit Cloneable
Klonen, was erklärt, die viele Nachteile des Ansatzes. ( Joshua Bloch ein Sun Mitarbeiter war, und führte die Entwicklung zahlreicher Java-Funktionen.)
Andere Tipps
klonbar selbst ist leider nur ein Marker-Interface, das heißt:. Es nicht die Methode clone () nicht definiert
Was tut, ist das Verhalten des geschützten Object.clone ändern () -Methode, die eine CloneNotSupportedException für Klassen werfen, die nicht klonbar implementieren und Mitglied weise flache Kopie für Klassen durchführen, die zu tun.
Auch wenn dies ist das Verhalten dem Sie suchen, werden Sie noch benötigen, um Ihre eigene Methode clone () zu implementieren, um sie öffentlich zu machen.
Wenn Sie Ihre eigenen Klon Umsetzung (), ist die Idee, mit dem Ziel zu starten, indem super.clone erstellen (), die garantiert der richtigen Klasse sein, und dann tun, um jede zusätzliche Bevölkerung von Feldern, falls eine flache Kopie ist nicht das, was Sie wollen. Aufruf eines Konstruktor von clone () wäre problematisch, da dieses Erbe im Falle einer Unterklasse ihre eigene zusätzliche klonbar Logik will brechen würde hinzuzufügen; wenn es nennt super.clone (), so wäre es eine Aufgabe der falschen Klasse in diesem Fall erhalten.
Dieser Ansatz umgeht jede Logik, die in Ihrem Konstrukteurs definiert werden, obwohl, die möglicherweise problematisch sein könnten.
Ein weiteres Problem ist, dass alle Unterklassen, die außer Kraft zu setzen Klon vergessen () automatisch erben Standard flache Kopie, die wahrscheinlich nicht das, was Sie im Falle von wandelbaren Zustand wollen (die zwischen der Quelle wird nun geteilt und die Kopie).
Die meisten Entwickler nicht verwenden klonbar aus diesen Gründen, und einfach eine Kopie Konstruktor implementieren statt.
Weitere Informationen und mögliche Gefahren von klonbar, ich das Buch Effective Java von Joshua Bloch sehr empfehlen
- Cloning ruft eine außersprachlichen Art und Weise Objekte zu konstruieren - ohne Konstrukteure.
- Klonen erfordert, dass Sie die Behandlung irgendwie mit CloneNotSupportedException -. Oder Client-Code stören sie für die Behandlung von
- Vorteile sind klein - Sie haben einfach nicht manuell kopieren Konstruktor schreiben .
So verwenden klonbar umsichtig. Es gibt Ihnen nicht genügend Vorteile im Vergleich zu dem Aufwand Sie alles richtig anwenden müssen tun.
Das Klonen ist eine grundlegende Programmierparadigma. Die Tatsache, dass Java es schlecht in vielerlei Hinsicht umgesetzt hat, kann gar nicht die Notwendigkeit für das Klonen zu verringern. Und es ist einfach zu implementieren, dass das Klonen funktioniert aber Sie sie haben wollen Arbeit, flach, tief, gemischt, was auch immer. Sie können sogar den Namen Klon für die Funktion verwenden und nicht implementieren klonbar wenn Sie so wollen.
Angenommen, ich habe die Klassen A, B und C, wobei B und C von A. ableiten Wenn ich eine Liste von Objekten des Typs A wie folgt aussehen:
ArrayList<A> list1;
Nun, das Liste Behälter enthält Objekte vom Typ A, B oder C. Sie wissen nicht, welche Art der Objekte sind. So können Sie die Liste wie diese nicht kopieren:
ArrayList<A> list2 = new ArrayList<A>();
for(A a : list1) {
list2.add(new A(a));
}
Wenn das Objekt tatsächlich vom Typ B oder C ist, werden Sie nicht die richtige Kopie erhalten. Und was ist, wenn A ist abstrakt? Nun haben einige Leute dies vorgeschlagen:
ArrayList<A> list2 = new ArrayList<A>();
for(A a : list1) {
if(a instanceof A) {
list2.add(new A(a));
} else if(a instanceof B) {
list2.add(new B(a));
} else if(a instanceof C) {
list2.add(new C(a));
}
}
Dies ist eine sehr, sehr schlechte Idee. Was passiert, wenn Sie einen neuen abgeleiteten Typ hinzufügen? Was passiert, wenn B oder C ist in einem anderen Paket, und Sie haben keinen Zugang zu ihnen in dieser Klasse?
Was Sie tun möchten, ist dies:
ArrayList<A> list2 = new ArrayList<A>();
for(A a : list1) {
list2.add(a.clone());
}
Viele Menschen haben gezeigt, warum die grundlegende Java-Implementierung von Klon problematisch ist. Aber es ist leicht auf diese Weise überwunden:
In der Klasse A:
public A clone() {
return new A(this);
}
In der Klasse B:
@Override
public B clone() {
return new B(this);
}
In der Klasse C:
@Override
public C clone() {
return new C(this):
}
Ich bin klonbar nicht Implementierung nur die gleiche Funktion Namen. Wenn Sie wie das nicht tun, nennen Sie es etwas anderes.
A) Es gibt nicht eine ganze Menge Vorteile des Klons über einen Copy-Konstruktor. Wahrscheinlich die größte ist die Fähigkeit, ein neues Objekt des exakt gleichen dynamischen Typs zu erstellen (unter der Annahme des deklarierte Typ clonable ist und eine öffentliche Klon-Methode).
B) Die Standard-Klon erzeugt eine flache Kopie, und es wird eine flache Kopie bleiben, es sei denn Ihre Klon Implementierung das ändert. Dies kann schwierig sein, vor allem, wenn Ihre Klasse hat letzte Felder
Bozho richtig ist, kann Klon schwierig sein, richtig zu machen. Eine Kopie Konstruktor / Fabrik werden die meisten Bedürfnisse dienen.
Was sind Nachteile klonbar?
Das Klonen ist sehr gefährlich, wenn das Objekt, den Sie kopieren composition.You Bedarf hat etwa unterhalb möglicher Nebenwirkung in diesem Fall zu denken, weil Klon flache Kopie erstellt:
Lassen Sie uns sagen, dass Sie ein Objekt haben DB ähnliche Manipulation zu handhaben. Sagen Sie, dass das Objekt Connection
Objekt als eines der Eigenschaft hat.
Also, wenn jemand Klon von originalObject
erstellt, das Objekt erstellt wird, sagen wir mal, cloneObject
.
Hier ist die originalObject
und cloneObject
halten die gleiche Referenz für Connection
Objekt.
Lassen Sie sagen originalObject
schließt das Connection
Objekt, so dass nun die cloneObject
wird nicht funktionieren, weil die connection
Objekt wurde zwischen ihnen geteilt und es wurde actaually durch die originalObject
geschlossen.
Ein ähnliches Problem kann auftreten, wenn wir sagen, dass Sie ein Objekt klonen möchten, die Iostream als Eigenschaft hat.
Wie funktioniert das rekursive Klonen passieren, wenn das Objekt ein zusammengesetztes Objekt ist?
klonbar führt flache Kopie. Bedeutung ist, dass Daten des Originalobjekts und Klon-Objekt auf die gleiche Referenz / Speicher verweisen. Gegenteil im Fall von tiefer Kopie, Daten aus dem Speicher des ursprünglichen Objekts in den Speicher des Klons Objekts kopiert wird.