Krótka odpowiedź na pytanie „dlaczego nie jest Cloneable
przestarzała?” (a właściwie, dlaczego nie są one X
przestarzałe, dla żadnego X
) jest takie, że nie poświęcono zbyt wiele uwagi ich wycofaniu.
Większość rzeczy, które zostały ostatnio wycofane, zostały wycofane, ponieważ istnieje określony plan ich usunięcia. Na przykład metody addPropertyChangeListener
i LogManagera zostały wycofane w Javie SE 8 z zamiarem usunięcia ich w Javie SE 9. (Przyczyną jest to, że niepotrzebnie komplikują one współzależności modułów). Rzeczywiście, te API zostały już usunięte z wczesnego rozwoju JDK 9 buduje. (Zauważ, że podobne wywołania detektora zmian właściwości zostały również usunięte z ; patrz JDK-8029806 ).removePropertyChangeListener
Pack200
Nie istnieje podobny plan dla Cloneable
i Object.clone()
.
Dłuższa odpowiedź wymagałaby omówienia dalszych pytań, takich jak to, czego można się spodziewać po tych interfejsach API, jakie koszty lub korzyści narosłyby platforma, gdyby zostały wycofane, i co jest przekazywane programistom, gdy interfejs API jest przestarzały. Omówiłem ten temat w moim ostatnim wykładzie JavaOne, Debt and Deprecation . (Slajdy dostępne pod tym linkiem; wideo tutaj ). Okazuje się, że sam JDK nie był zbyt konsekwentny w używaniu wycofania. Kiedyś oznaczało kilka różnych rzeczy, w tym na przykład
Jest to niebezpieczne i należy zdawać sobie sprawę z ryzyka związanego z użyciem (przykład: Thread.stop()
, Thread.resume()
, i Thread.suspend()
).
To zostanie usunięte w przyszłej wersji
To jest przestarzałe i dobrym pomysłem jest użycie czegoś innego (przykład: wiele metod w java.util.Date
)
Wszystkie mają różne znaczenia, a różne ich podzbiory mają zastosowanie do różnych przestarzałych rzeczy. Niektóre z nich mają zastosowanie do rzeczy, które nie są przestarzałe (ale które mogą być przestarzałe).
Cloneable
i Object.clone()
są „zepsute” w tym sensie, że mają wady konstrukcyjne i są trudne w użyciu. Jednak clone()
nadal jest to najlepszy sposób kopiowania tablic, a klonowanie ma pewną ograniczoną przydatność do tworzenia kopii instancji klas, które są starannie zaimplementowane. Usunięcie klonowania byłoby niekompatybilną zmianą, która zepsułaby wiele rzeczy. Operację klonowania można by ponownie zaimplementować w inny sposób, ale prawdopodobnie byłoby to wolniejsze niż Object.clone()
.
Jednak dla większości rzeczy konstruktor kopiujący jest lepszy niż klonowanie. Być może więc oznaczenie Cloneable
jako „przestarzałe” lub „zastąpione” lub coś podobnego byłoby właściwe. To powiedziałoby programistom, że prawdopodobnie chcą szukać gdzie indziej, ale nie oznaczałoby to, że mechanizm klonowania może zostać usunięty w przyszłej wersji. Niestety takiego znacznika nie ma.
W obecnym stanie rzeczy „wycofanie z użycia” wydaje się oznaczać ostateczne usunięcie - pomimo faktu, że zniknęła znikoma liczba przestarzałych funkcji, które zostały kiedykolwiek usunięte - i dlatego wycofanie nie wydaje się uzasadnione w przypadku mechanizmu klonowania. Być może w przyszłości będzie można zastosować alternatywne oznakowanie, które nakłania programistów do stosowania alternatywnych mechanizmów.
AKTUALIZACJA
Dodałem dodatkową historię do raportu o błędzie . Frank Yellin, wczesny implementator JVM i współautor specyfikacji JVM, poczynił kilka komentarzy w odpowiedzi na komentarz „zagubiony we mgle czasu” w rekomendacji TRC cytowanej w drugiej odpowiedzi . Zacytowałem tutaj odpowiednie fragmenty; pełna wiadomość znajduje się w zgłoszeniu błędu.
Cloneable nie ma metod z tego samego powodu co Serializable. Cloneable wskazuje właściwość klasy, zamiast mówić cokolwiek o metodach obsługiwanych przez klasę.
Przed refleksją potrzebowaliśmy natywnej metody do wykonania płytkiej kopii obiektu. Tak narodził się Object.clone (). Było również jasne, że wiele klas chciałoby zastąpić tę metodę i że nie każda klasa chciałaby zostać sklonowana. Dlatego narodził się Cloneable, aby wskazać zamiary programisty.
Krótko mówiąc. Celem Cloneable nie było wskazanie, że masz publiczną metodę clone (). Miało to na celu wskazanie, że chcesz zostać sklonowany za pomocą Object.clone (), a implementacja zadecydowała, czy upublicznić clone ().