Es ist allgemein bekannt, dass die Cloneable
Schnittstelle in Java defekt ist. Es gibt viele Gründe dafür, die ich nicht erwähnen werde; andere haben es schon getan. Es ist auch die Position der Java-Architekten selbst.
Meine Frage ist daher: Warum wurde noch nicht veraltet? Wenn das Java-Kernteam entschieden hat, dass es defekt ist, muss es auch die Ablehnung in Betracht gezogen haben. Was sind ihre Gründe dagegen (in Java 8 ist es immer noch nicht veraltet )?
Cloneable
ist weithin bekannt.Antworten:
Es gibt einen Fehler, der 1997 bei der Java Bug Database über das Hinzufügen von
clone()
Methoden zu gemeldet wurdeCloneable
, sodass er nicht mehr unbrauchbar wäre. Es wurde mit der Entschließung "wird nicht behoben" geschlossen und die Begründung lautete wie folgt:Obwohl dies nicht direkt veraltet ist , liegt der Grund dafür, dass Cloneable nicht "veraltet" ist, darin, dass das Technical Review Comitee entschieden hat, dass die Änderung der vorhandenen Dokumentation ausreicht , um diese Schnittstelle nützlich zu machen. Und so taten sie es. Bis Java 1.4
Cloneable
wurde wie folgt dokumentiert:Seit Java 1.4 (das im Februar 2002 veröffentlicht wurde) bis zur aktuellen Ausgabe (Java 8) sieht es folgendermaßen aus:
quelle
clone
Methode überhaupt warObject
?Object#clone()
Erzeugt eine Instanz derselben Klasse wie das Original, ohne dass diese Klasse zur Kompilierungszeit bekannt ist.Die kurze Antwort auf "Warum ist nicht
Cloneable
veraltet?" (oder in der Tat, warum wird es nichtX
veraltetX
) ist, dass nicht viel darauf geachtet wurde, sie zu verwerfen.Die meisten Dinge, die kürzlich veraltet waren, wurden veraltet, weil es einen bestimmten Plan gibt, sie zu entfernen. Zum Beispiel können die
addPropertyChangeListener
undremovePropertyChangeListener
Methoden der LogManager wurden als veraltet in Java SE 8 (ist der Grund , dass sie Modul Interdependenzen unnötig kompliziert.) Mit der Absicht, sie in Java SE 9. Entfernen der Tat haben diese APIs bereits von Anfang JDK 9 entfernt Entwicklung baut. (Beachten Sie, dass ähnliche Listener-Aufrufe zur Änderung von Eigenschaften auch aus entfernt wurdenPack200
; siehe JDK-8029806 .)Für
Cloneable
und gibt es keinen ähnlichen PlanObject.clone()
.Eine längere Antwort würde die Erörterung weiterer Fragen beinhalten, z. B. was mit diesen APIs zu erwarten ist, welche Kosten oder Vorteile der Plattform entstehen würden, wenn sie veraltet wären, und was den Entwicklern mitgeteilt wird, wenn eine API veraltet ist. Ich habe dieses Thema in meinem letzten JavaOne-Vortrag " Schulden und Verfall" untersucht . (Folien unter diesem Link verfügbar; Video hier .) Es stellt sich heraus, dass das JDK selbst in seiner Verwendung von Verfall nicht sehr konsistent war. Es wurde verwendet, um verschiedene Dinge zu bedeuten, einschließlich zum Beispiel:
Dies ist gefährlich , und Sie sollten die Risiken der Verwendung es bewusst sein (Beispiel:
Thread.stop()
,Thread.resume()
, undThread.suspend()
).Dies wird in einer zukünftigen Version entfernt
Dies ist veraltet und es ist eine gute Idee, etwas anderes zu verwenden (Beispiel: viele der Methoden in
java.util.Date
)All dies sind unterschiedliche Bedeutungen, und verschiedene Untergruppen davon gelten für verschiedene Dinge, die veraltet sind. Und einige Untergruppen davon gelten für Dinge, die nicht veraltet sind (die aber möglicherweise veraltet sein sollten).
Cloneable
undObject.clone()
sind "kaputt" in dem Sinne, dass sie Designfehler aufweisen und schwer richtig zu verwenden sind. Diesclone()
ist jedoch immer noch der beste Weg, um Arrays zu kopieren, und das Klonen ist nur begrenzt nützlich, um Kopien von Instanzen von Klassen zu erstellen, die sorgfältig implementiert wurden. Das Entfernen des Klonens wäre eine inkompatible Änderung, die viele Dinge kaputt machen würde. Ein Klonvorgang könnte auf andere Weise erneut implementiert werden, wäre aber wahrscheinlich langsamer alsObject.clone()
.In den meisten Fällen ist jedoch ein Kopierkonstruktor dem Klonen vorzuziehen. Vielleicht
Cloneable
wäre es angebracht , sie als "veraltet" oder "ersetzt" oder ähnliches zu markieren . Dies würde Entwicklern mitteilen, dass sie wahrscheinlich woanders suchen möchten, aber es würde nicht signalisieren, dass der Klonmechanismus in einer zukünftigen Version möglicherweise entfernt wird. Leider existiert kein solcher Marker.Aus heutiger Sicht scheint "Abwertung" eine eventuelle Entfernung zu bedeuten - trotz der Tatsache, dass eine verschwindend kleine Anzahl veralteter Features jemals entfernt wurde - und daher scheint eine Abwertung für den Klonmechanismus nicht gerechtfertigt zu sein. Vielleicht kann in Zukunft eine alternative Kennzeichnung angewendet werden, die Entwickler anweist, stattdessen alternative Mechanismen zu verwenden.
AKTUALISIEREN
Ich habe dem Fehlerbericht einen zusätzlichen Verlauf hinzugefügt . Frank Yellin, ein früher JVM-Implementierer und Mitautor der JVM-Spezifikation, gab einige Kommentare als Antwort auf den Kommentar "Verloren im Nebel der Zeit" in der in der anderen Antwort zitierten TRC-Empfehlung ab . Ich habe die relevanten Teile hier zitiert; Die vollständige Meldung befindet sich im Fehlerbericht.
quelle
Object.clone()
ins Feuer werfen, nur weil alle anderen es wollen, sondern auch bereit sind, zu argumentieren und die guten Dinge zur Sprache zu bringen.array.clone()
es notwendigerweise schneller ist als irgendwelche Alternativen. Aus API-Sicht ist dies die präziseste Methode zum Duplizieren eines Arrays.Arrays.copyOf(array, newlen)
kommt nahe, erfordert jedoch einen Längenparameter, der redundant ist, wenn Sie die Länge nicht ändern.Thread.suspend()
und obwohl wir uns einig sind, dass undThread.stop()
(no-arg) gefährlich sind, sie wahrscheinlich nicht entfernt oder geändert werden, um eine Ausnahme bedingungslos auszulösen, weil die Leute sie tatsächlich verwenden! Vermutlich sind sie bereit, das Risiko zu tragen. Einer der mildernden Faktoren bei den Listenern für Eigenschaftsänderungen ist, dass sie sehr selten verwendet wurden, sodass die Auswirkungen ihrer Entfernung gering sind.java.beans
könnte unabhängig gemacht werden,java.desktop
da Beans nur eine Bibliotheks-API für Eigenschaften sind. Wenn Sie sich in die Beans-API vertiefen, gibt es leider viele Abhängigkeiten von AWT. Die Implementierung hat noch mehr. Sicherlich könnte es möglich sein, sie zu befreien, aber dies scheint viel mehr Arbeit zu sein, als beispielsweise die Protokollierung von Bohnen zu entschlüsseln. Bei der gesamten Modularisierung geht es darum, diese Entflechtung durchzuführen. Zweifellos könnte mehr getan werden, aber dann würde Jigsaw noch länger dauern.Weil die JCP dies nicht für richtig gehalten hat und dies möglicherweise niemals tun wird. Frag sie. Du fragst am falschen Ort.
Aufgrund der Abwärtskompatibilitätsanforderungen wird niemand jemals etwas aus der Java-API entfernen. Das letzte Mal geschah 1996/7 die Änderung des AWT-Ereignismodells zwischen 1,0 und 1,1.
quelle
Thread.stop(Throwable)
indem sie ihren Vertrag so geändert habenUnsupportedOperationException
, dass er immer zum Anrufer (nicht zum Ziel-Thread!) Wirft.Thread.stop(Throwable)
Funktionalität erfolgte in Java 8. Wie auch immer, der uneingeschränkte Rat, sie zu "fragen", ist falsch, da der Chef-Java-Architekt selbst heute ein aktives Mitglied bei Stack Overflow ist. Er beantwortet einfach nichts anderes als Streams-bezogene Fragen.Cloneable
von der Java-API entfernt wird. Ich frage, warum es nicht abgelenkt wird. Und ich denke, dies ist ein perfekter Ort zum Fragen.