Was ist der konkrete Grund dafür clone()
ist als geschützt definiert in java.lang.Object
?
Warum ist die Methode clone() in java.lang.Object geschützt?
Alex N.
oxbow_lakes
Die Tatsache, dass der Klon geschützt ist, ist äußerst zweifelhaft – ebenso wie die Tatsache, dass die clone
Methode ist nicht in deklariert Cloneable
Schnittstelle.
Es macht die Methode ziemlich nutzlos, um Kopien von Daten zu machen, weil du kannst nicht sagen:
if(a instanceof Cloneable) {
copy = ((Cloneable) a).clone();
}
Ich denke, dass das Design von Cloneable
ist jetzt weitgehend als Fehler angesehen (Zitat unten). Normalerweise möchte ich in der Lage sein, Implementierungen einer Schnittstelle vorzunehmen Cloneable
aber nicht unbedingt die Schnittstelle machen Cloneable
(ähnlich der Verwendung von Serializable
). Das geht nicht ohne Reflexion:
ISomething i = ...
if (i instanceof Cloneable) {
//DAMN! I Need to know about ISomethingImpl! Unless...
copy = (ISomething) i.getClass().getMethod("clone").invoke(i);
}
Zitat von Josh Blochs Effektives Java:
“Die Cloneable-Schnittstelle war als Mixin-Schnittstelle für Objekte gedacht, um anzuzeigen, dass sie das Klonen zulassen. Leider erfüllt sie diesen Zweck nicht … Dies ist eine höchst atypische Verwendung von Schnittstellen und keine, die emuliert werden sollte … Zur Implementierung Damit die Schnittstelle Auswirkungen auf eine Klasse hat, müssen sie und alle ihre Oberklassen a befolgen ziemlich komplexes, nicht durchsetzbares und weitgehend undokumentiertes Protokoll“
-
Wenn das Objekt nicht klonbar ist, löst clone() von Object CloneNotSupportedException aus. Sie müssen also klonbar sein, wenn Sie super.clone() aufrufen (was dazu führt, dass Object.clone() aufgerufen wird). Ich sehe nicht, wie ein Objekt serialisiert werden kann, ohne Serializable zu implementieren.
– Steve Kuo
16. Juli 09 um 17:00 Uhr
-
Entschuldigung – das wollte ich nicht sagen. Ich habe lediglich angedeutet, dass “gutes” Design dazu gehört nicht eine Schnittstelle erweitern
Serializable
– Es obliegt den Implementierungen, über die Implementierung zu entscheidenSerializable
. Ich erweiterte dies aufCloneable
– Es ist nicht etwas, was eine Schnittstelle erweitern sollte – aber eine Implementierung einer Schnittstelle ist frei zu seinCloneable
. Das Problem ist, wenn Sie einen Parameter des Schnittstellentyps haben, fragen Sie ihn, ob er klonbar ist; aber dann können Sie es nicht wirklich klonen!– oxbow_lakes
16. Juli 09 um 17:11 Uhr
-
Das Wort “Fehler” taucht nirgendwo in Ihrem Angebot auf. Und das Buch eines Mannes bedeutet nicht, dass es “weithin angesehen” ist. Ich würde Folgendes argumentieren: 1) Die Schnittstelle “Cloneable” soll nicht angeben, dass eine Klasse eine öffentliche Klonmethode hatte oder dass eine Klasse ein öffentliches Verhalten hatte. Es ist schlecht benannt, weil es die Leute dazu verleiten könnte, das zu denken. 2) Es gibt keine Schnittstelle in Java, die anzeigt, ob eine Klasse geklont werden könnte. Allerdings gibt es für vieles, was man sich wünscht, keine Schnittstellen. Dies bedeutet nicht, dass es sich um einen “Fehler” handelt.
– neues Konto
23. März 11 um 4:58 Uhr
-
@oxbow_lakes: Das Design von Clone und Cloneable ist hier nicht das Hauptanliegen, die Frage ist, warum “geschützt” (im Gegensatz zu warum nicht “öffentlich”). Wie auch immer Ihre Antwort lautet, das sollte auch erklären, warum „finalize“ geschützt ist und warum andere Methoden wie „toString“ „öffentlich“ und nicht „geschützt“ sind.
– KGhatak
16. Juni 16 um 10:43 Uhr
-
@newacct “… das Buch eines Mannes bedeutet nicht, dass es allgemein angesehen wird …” Es ist nicht das Buch eines beliebigen Mannes. Joshua Bloch ist der Schöpfer der Java-Sprache. Wenn er glaubt, dass das Cloneable-Interface kaputt ist, dann können wir dem nicht widersprechen.
– BOT_bkcd
11. November 21 um 7:46 Uhr
Die Clonable-Schnittstelle ist nur eine Markierung, die besagt, dass die Klasse das Klonen unterstützen kann. Die Methode ist geschützt, weil Sie sie nicht für ein Objekt aufrufen sollten, Sie können (und sollten) sie als öffentlich überschreiben.
Von Sonne:
In der Klasse Object ist die Methode clone() als geschützt deklariert. Wenn Sie nur Cloneable implementieren, können nur Unterklassen und Mitglieder desselben Pakets clone() für das Objekt aufrufen. Damit jede Klasse in einem beliebigen Paket auf die Methode clone() zugreifen kann, müssen Sie sie überschreiben und als öffentlich deklarieren, wie unten beschrieben. (Wenn Sie eine Methode überschreiben, können Sie sie weniger privat, aber nicht privater machen. Hier wird die geschützte clone()-Methode in Object als öffentliche Methode überschrieben.)
-
Was gut ist, bis Sie Interfaces in den Mix einbringen – versuchen und versuchen, eine unbekannte Implementierung von zu klonen
Set
– oxbow_lakes
16. Juli 09 um 16:57 Uhr
-
@oxbow_lakes: aber vielleicht sind einige Implementierungen von Set nicht klonbar
– neues Konto
16. Juli 09 um 17:25 Uhr
-
Sie können nichts klonen, das die Clonable-Schnittstelle nicht implementiert – es ist eine Markierung, die sagt: „Diese Klasse ist ordnungsgemäß klonbar“ – sehr ähnlich der Serializable-Schnittstelle. Übrigens gibt es eine Möglichkeit, Klassen über Serialisierung zu klonen, die gut funktioniert – googeln Sie etwas wie “Java Serialization Clone”, und Sie werden wahrscheinlich eine Handvoll Möglichkeiten finden, eine tiefe Kopie Ihres Objekts zu erhalten.
– Bill K
16. Juli 09 um 20:00 Uhr
-
Sie können nichts klonen, das die Cloneable-Schnittstelle nicht implementiert, aber nur weil etwas die Cloneable-Schnittstelle implementiert, bedeutet das nicht, dass Sie es klonen können.
– Michael myers
♦24. Juli 09 um 22:23 Uhr
-
@BuckCherry toString hat eine Standardimplementierung, wenn Sie es aufrufen, passiert etwas Gutes und Sie erhalten einen String zurück. equals hat eine Standardimplementierung (wie ==). Clone kann keine Standardimplementierung haben. Wenn Sie clone für ein Objekt aufrufen, das es nicht implementiert hat, erhalten Sie kein vernünftiges Verhalten. Das Klonen ist kompliziert und kann nicht wirklich automatisch durchgeführt werden (einige Objekte ohne Standardkonstruktoren können möglicherweise nicht generisch geklont werden), daher machen sie es standardmäßig etwas sicherer. Ich denke jedoch, dass es vielleicht gar nicht nötig gewesen wäre, es überhaupt auf Object zu setzen.
– Bill K
16. Juni 16 um 16:02 Uhr
clone
ist geschützt, weil es etwas ist, das überschrieben werden sollte, damit es für die aktuelle Klasse spezifisch ist. Es wäre zwar möglich, eine Öffentlichkeit zu schaffen clone
Methode, die irgendein Objekt klonen würde, wäre dies nicht so gut wie eine Methode, die speziell für die Klasse geschrieben wurde, die sie benötigt.
-
aber warum muss es dafür geschützt werden?
– Janusz
16. Juli 09 um 16:31 Uhr
-
Es ist geschützt, sodass Sie das im Objekt nicht verwenden (es wird sowieso nur eine Ausnahme auslösen). Sie wollen, dass Sie es in einer Klasse außer Kraft setzen, dann machen Sie es öffentlich. (unten auch ein paar Mal beantwortet)
– Bill K
16. Juli 09 um 16:41 Uhr
-
Und nutzlos bei der Betrachtung von Schnittstellen gemäß meinem Punkt unten
– oxbow_lakes
16. Juli 09 um 17:19 Uhr
-
sollte überschrieben werden, ist nicht sehr klar, dann hätte es abstrakt sein sollen und dann nicht in der Objektklasse, ich bemühe mich sehr zu verstehen, warum das so ist.
– Kumar Abhishek
6. Januar 17 um 18:08 Uhr
Die Clone-Methode kann nicht direkt auf ein Objekt angewendet werden, weshalb sie von der Unterklasse überschrieben werden soll.
Natürlich könnte es öffentlich sein und nur eine entsprechende Ausnahme auslösen, wenn das Klonen nicht möglich ist, aber ich denke, das wäre irreführend.
Die Art und Weise, wie Klonen derzeit implementiert wird, lässt Sie darüber nachdenken, warum Sie Klonen verwenden möchten und wie Ihr Objekt geklont werden soll.
Michaela Maura Elschner
IMHO ist es so einfach:
#clone
darf nicht auf nicht klonbaren Objekten aufgerufen werden, daher wird es nicht veröffentlicht#clone
muss von Unterklassen ob aufgerufen werdenObject
die Cloneable implementieren, um die flache Kopie der richtigen Klasse zu erhalten
Was ist der richtige Umfang für Methoden, die von Unterklassen aufgerufen werden können, aber nicht von anderen Klassen?
Es ist protected
.
Klassen implementieren Cloneable
natürlich wird diese Methode öffentlich gemacht, damit sie von anderen Klassen aufgerufen werden kann.
Karl Manaster
Es ist geschützt, da die Standardimplementierung eine flache mitgliederweise Kopie aller Felder (einschließlich privater) erstellt. Konstruktor umgehen. Dies ist nicht etwas, wofür ein Objekt von vornherein ausgelegt sein könnte (z. B. könnte es erstellte Objektinstanzen in einer gemeinsam genutzten Liste verfolgen oder ähnliches).
Aus dem gleichen Grund ist die Standardimplementierung von clone()
wird ausgelöst, wenn das aufgerufene Objekt nicht implementiert wird Cloneable
. Es handelt sich um einen potenziell unsicheren Vorgang mit weitreichenden Folgen, und daher muss der Autor der Klasse ausdrücklich zustimmen.
Aus dem javadoc von cloneable.
* By convention, classes that implement this interface (cloneable) should override
* <tt>Object.clone</tt> (which is protected) with a public method.
* See {@link java.lang.Object#clone()} for details on overriding this
* method.
* Note that this interface does <i>not</i> contain the <tt>clone</tt> method.
* Therefore, it is not possible to clone an object merely by virtue of the
* fact that it implements this interface. Even if the clone method is invoked
* reflectively, there is no guarantee that it will succeed.
Sie könnten also für jedes Objekt den Klon aufrufen, aber dies würde Ihnen die meiste Zeit nicht die gewünschten Ergebnisse oder eine Ausnahme liefern. Aber wird nur empfohlen, wenn Sie klonbar implementieren.
-
Sie kann nicht Rufen Sie Klonen für jedes Objekt auf, weil es geschützt ist!
– Pavel Minaev
16. Juli 09 um 16:56 Uhr
.