Powszechnie wiadomo, że Cloneable
interfejs w Javie jest uszkodzony. Jest ku temu wiele powodów, o których nie wspomnę; inni już to zrobili. Jest to również stanowisko samych architektów Javy .
Moje pytanie brzmi zatem: dlaczego nie zostało jeszcze wycofane? Jeśli główny zespół Java zdecydował, że jest uszkodzony, musiał również rozważyć jego wycofanie. Jakie są ich powody, aby to zrobić (w Javie 8 nadal nie jest przestarzałe )?
Cloneable
Powszechnie znana jest ich własna krytyka .Odpowiedzi:
Jest bug złożony w 1997 roku do Java Database Bug o dodanie
clone()
metodyCloneable
, więc to nie będzie bezużyteczna. Został zamknięty postanowieniem „nie naprawi”, a uzasadnienie było następujące:Tak więc, chociaż nie chodzi bezpośrednio o wycofanie z użycia , powodem tego, że Cloneable nie jest „przestarzały”, jest fakt, że komitet ds. Przeglądu technicznego zdecydował, że modyfikacja istniejącej dokumentacji będzie wystarczająca, aby uczynić ten interfejs użytecznym. I tak zrobili. Aż do wersji Java 1.4
Cloneable
dokumentowano w następujący sposób:Od wersji Java 1.4 (która została wydana w lutym 2002) do aktualnej edycji (Java 8) wygląda to tak:
źródło
clone
metoda byłaObject
na pierwszym miejscu?Object#clone()
tworzy instancję tej samej klasy, co oryginał, bez znajomości tej klasy w czasie kompilacji.Krótka odpowiedź na pytanie „dlaczego nie jest
Cloneable
przestarzała?” (a właściwie, dlaczego nie są oneX
przestarzałe, dla żadnegoX
) 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
iObject.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()
, iThread.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
iObject.clone()
są „zepsute” w tym sensie, że mają wady konstrukcyjne i są trudne w użyciu. Jednakclone()
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.
źródło
Object.clone()
do ognia tylko dlatego, że wszyscy tego chcą, ale jesteś skłonny uzasadnić i wspomnieć o dobrych rzeczach.array.clone()
niekoniecznie jest to szybsze niż jakiekolwiek alternatywy. Z punktu widzenia API jest to najbardziej zwięzły sposób na zduplikowanie tablicy.Arrays.copyOf(array, newlen)
zbliża się, ale wymaga parametru długości, który jest zbędny, jeśli nie zmieniasz długości.Thread.suspend()
iThread.stop()
(no-arg) są niebezpieczne, prawdopodobnie nie zostaną one usunięte - ani zmienione, aby bezwarunkowo zgłosić wyjątek - ponieważ ludzie faktycznie ich używają! Przypuszczalnie są gotowi ponieść ryzyko. Jednym z czynników ograniczających nasłuchiwanie zmian właściwości jest to, że były one używane bardzo rzadko, więc wpływ ich usunięcia jest niewielki.java.beans
mógłby zostać uniezależniony,java.desktop
ponieważ ziarna są tylko biblioteką API dla właściwości. Niestety, jeśli zagłębisz się w API Bean, istnieje wiele zależności od AWT. Wdrożenie ma jeszcze więcej. Z pewnością można je wydobyć, ale wykonanie tego wydaje się dużo bardziej pracochłonne niż, powiedzmy, wyłapywanie kłód z fasoli. Cały wysiłek związany z modularyzacją polega na tym rozplątywaniu; niewątpliwie można by zrobić więcej, ale wtedy Jigsaw trwałoby jeszcze dłużej.Ponieważ JCP nie uznał tego za stosowne i może nigdy tego nie uczynić. Poprosić ich. Pytasz w złym miejscu.
Nikt nigdy nie usunie niczego z Java API z powodu wymogu kompatybilności wstecznej. Ostatnim razem, kiedy to się stało, była zmiana modelu zdarzenia AWT pomiędzy 1.0 a 1.1 w 1996/7.
źródło
Thread.stop(Throwable)
, zmieniając jego kontrakt, aby zawsze rzucałUnsupportedOperationException
do wywołującego (nie do wątku docelowego!).Thread.stop(Throwable)
funkcjonalności miało miejsce w Javie 8. W każdym razie, niekwalifikowana rada, aby „zapytać ich” jest błędna, ponieważ sam główny architekt Javy jest aktywnym członkiem Stack Overflow. Po prostu nie zawraca sobie głowy odpowiadaniem na nic poza pytaniami dotyczącymi strumieni.Cloneable
zostanie usunięty z Java API. Pytam, dlaczego nie zostanie pozbawiony. Myślę, że to idealne miejsce na zadawanie pytań.