Przede wszystkim polecam ten artykuł: Java: Kiedy stworzyć ostateczną klasę
Jeśli tak, to kiedy go używają, abym mógł lepiej to zrozumieć i wiedzieć, kiedy go użyć.
final
Klasa jest po prostu klasa, która nie może zostać przedłużony .
(Nie oznacza to, że wszystkie odwołania do obiektów tej klasy działałyby tak, jakby były zadeklarowane jako final
.)
Gdy przydatne jest zadeklarowanie klasy jako końcowej, jest ona uwzględniona w odpowiedziach na to pytanie:
Jeśli Java jest zorientowana obiektowo, a ty deklarujesz klasę final
, to czy nie oznacza to, że klasa ma cechy obiektów?
W pewnym sensie tak.
Oznaczając klasę jako końcową, wyłączasz potężną i elastyczną funkcję języka dla tej części kodu. Niektóre klasy nie powinny jednak (a w niektórych przypadkach nie mogą ) być zaprojektowane w taki sposób, aby odpowiednio uwzględnić podklasę. W takich przypadkach sensowne jest oznaczenie klasy jako ostatecznej, mimo że ogranicza ona OOP. (Pamiętaj jednak, że klasa końcowa może nadal przedłużyć inną klasę niefinałową).
W Javie elementów z
final
modyfikatorem nie można zmienić!Obejmuje to końcowe klasy, końcowe zmienne i końcowe metody:
źródło
final
modyfikatorem nie można zmienić!” Jest zbyt kategoryczne i w rzeczywistości nie do końca poprawne. Jak to ujął Grady Booch: „Obiekt ma stan, zachowanie i tożsamość”. Chociaż nie możemy zmienić tożsamości obiektu, gdy odniesienie zostanie oznaczone jako ostateczne, mamy szansę zmienić jego stan poprzez przypisanie nowych wartości dofinal
pól innych (pod warunkiem, że oczywiście je ma). Każdy, kto jest planując uzyskanie certyfikatu Oracle Java (takiego jak 1Z0-808 itp.) należy o tym pamiętać, ponieważ na egzaminie mogą pojawić się pytania dotyczące tego aspektu ...Jeden scenariusz, w którym ze względów bezpieczeństwa ważna jest ostateczność, gdy chcesz zapobiec dziedziczeniu klasy. Pozwala to upewnić się, że uruchomiony kod nie jest przez nikogo nadpisywany .
Kolejny scenariusz dotyczy optymalizacji: wydaje mi się, że pamiętam, że kompilator Java zawiera niektóre wywołania funkcji z klas końcowych. Jeśli więc zadzwonisz,
a.x()
a a zostanie zadeklarowanefinal
, wiemy w czasie kompilacji, jaki będzie kod i można go włączyć do funkcji wywołującej. Nie mam pojęcia, czy rzeczywiście tak się dzieje, ale ostatecznie jest taka możliwość.źródło
Najlepszym przykładem jest
która jest niezmienną klasą i nie może być przedłużona. Oczywiście jest coś więcej niż uczynienie klasy ostatecznej niezmienną.
źródło
Odpowiednia lektura: Zasada otwartego i zamkniętego autorstwa Boba Martina.
Kluczowy cytat:
Słowo
final
kluczowe służy do wymuszenia tego w Javie, niezależnie od tego, czy jest używane w metodach, czy w klasach.źródło
final
powoduje, że klasa jest zamknięta dla rozszerzenia, a nie otwarta? Czy też biorę to zbyt dosłownie?final
deklaracji klasy / metody nie ma sensu, jeśli chcesz, aby kod implementacji został zamknięty w celu modyfikacji, ale otwarty do rozszerzenia przez dziedziczenie.Jeśli wyobrażasz sobie hierarchię klas jako drzewo (jak w Javie), klasy abstrakcyjne mogą być tylko gałęziami, a klasy końcowe to te, które mogą być tylko liśćmi. Klasy, które nie należą do żadnej z tych kategorii, mogą być zarówno gałęziami, jak i liśćmi.
Tu nie ma naruszenia zasad OO, finał po prostu zapewnia niezłą symetrię.
W praktyce chcesz użyć opcji końcowej, jeśli chcesz, aby Twoje obiekty były niezmienne lub jeśli piszesz interfejs API, aby zasygnalizować użytkownikom interfejsu API, że klasa nie jest przeznaczona do rozszerzenia.
źródło
Samo słowo kluczowe
final
oznacza, że coś jest ostateczne i nie powinno być w żaden sposób modyfikowane. Jeśli klasa jest oznaczona,final
nie można jej rozszerzyć ani podklasować. Ale pytanie brzmi: dlaczego oceniamy klasęfinal
? IMO ma różne przyczyny:Słyszałem, że ocena klasy
final
poprawia wydajność, ale szczerze mówiąc, nie mogłam znaleźć tego argumentu, który miałby dużą wagę.Być może tak, ale czasem taki jest zamierzony cel. Czasami robimy to, aby osiągnąć większe korzyści z bezpieczeństwa itp., Poświęcając zdolność tej klasy do rozszerzenia. Ale klasa końcowa może w razie potrzeby rozszerzyć jedną klasę.
Z drugiej strony powinniśmy preferować kompozycję zamiast dziedziczenia, a
final
słowo kluczowe faktycznie pomaga w egzekwowaniu tej zasady.źródło
Bądź ostrożny, kiedy uczynisz klasę „końcową”. Ponieważ jeśli chcesz napisać test jednostkowy dla końcowej klasy, nie możesz podklasować tej końcowej klasy, aby zastosować technikę rozbijania zależności „Metoda podklasy i przesłonięcia” opisana w książce Michaela C. Feathersa „Skuteczna praca ze starszym kodem” . W tej książce Feathers powiedział: „Poważnie, łatwo jest uwierzyć, że zapieczętowane i ostateczne są błędnym błędem, że nigdy nie powinny były być dodawane do języków programowania. Ale prawdziwa wina leży po naszej stronie. Gdy polegamy bezpośrednio na biblioteki, które są poza naszą kontrolą, po prostu prosimy o kłopoty ”.
źródło
final class
można uniknąć zepsucia publicznego interfejsu API podczas dodawania nowych metodZałóżmy, że w wersji 1 swojej
Base
klasy robisz:a klient:
Następnie, jeśli w wersji 2 chcesz dodać
method
metodę doBase
:zepsułby kod klienta.
Gdybyśmy zastosowali
final class Base
zamiast tego, klient nie byłby w stanie dziedziczyć, a dodanie metody nie spowodowałoby uszkodzenia interfejsu API.źródło
Jeśli klasa jest oznaczona
final
, oznacza to, że jej struktura nie może być modyfikowana przez nic zewnętrznego. Tam, gdzie jest to najbardziej widoczne, kiedy wykonujesz tradycyjne dziedziczenie polimorficzne, w zasadzieclass B extends A
po prostu nie zadziała. Jest to w zasadzie sposób ochrony niektórych części twojego kodu (do pewnego stopnia) .Aby wyjaśnić, oznaczanie klasy
final
nie oznacza jej pól jakofinal
takich i jako takie nie chroni właściwości obiektu, ale rzeczywistą strukturę klasy.źródło
ABY ROZWIĄZYWAĆ PROBLEM Z KLASĄ KOŃCOWĄ:
Istnieją dwa sposoby na zakończenie klasy. Pierwszym z nich jest użycie słowa kluczowego final w deklaracji klasy:
Drugim sposobem na zakończenie klasy jest zadeklarowanie wszystkich jej konstruktorów jako prywatnych:
Oznaczenie go jako końcowego oszczędza kłopotów, jeśli dowiesz się, że jest to rzeczywiście finał, aby zademonstrować spojrzenie na tę klasę testu. na pierwszy rzut oka wygląda publicznie.
Niestety, ponieważ jedyny konstruktor klasy jest prywatny, nie można rozszerzyć tej klasy. W przypadku klasy Test nie ma powodu, aby klasa była ostateczna. Klasa Test jest dobrym przykładem tego, w jaki sposób niejawne klasy końcowe mogą powodować problemy.
Powinieneś więc oznaczyć go jako ostateczny, gdy domyślnie uczynisz klasę końcową, czyniąc ją konstruktorem prywatną.
źródło
Klasa końcowa to klasa, której nie można przedłużyć. Również metody można zadeklarować jako ostateczne, aby wskazać, że nie można ich zastąpić podklasami.
Zapobieganie podzklasowaniu klasy może być szczególnie przydatne, jeśli piszesz interfejsy API lub biblioteki i chcesz uniknąć rozszerzenia w celu zmiany podstawowego zachowania.
źródło
Jedna zaleta utrzymania klasy jako ostatecznej:
Klasa string jest utrzymywana jako ostateczna, aby nikt nie mógł przesłonić jej metod i zmienić funkcjonalności. np. nikt nie może zmienić funkcjonalności metody length (). Zawsze zwróci długość łańcucha.
Deweloper tej klasy nie chciał, aby ktokolwiek zmienił funkcjonalność tej klasy, więc utrzymał ją jako ostateczną.
źródło
Tak, czasem możesz tego chcieć ze względów bezpieczeństwa lub ze względu na szybkość. Odbywa się to również w C ++. To nie może być , że zastosowanie do programów, ale moreso szkieletowe. http://www.glenmccl.com/perfj_025.htm
źródło
W języku Java ostateczne użycie słowa kluczowego w poniższych przypadkach.
źródło
Klasy końcowe nie mogą być przedłużane. Jeśli więc chcesz, aby klasa zachowywała się w określony sposób i nie pozwalała komuś przesłonić metod (z możliwie mniej wydajnym i bardziej złośliwym kodem), możesz zadeklarować całą klasę jako ostateczne lub specyficzne metody, którymi nie chcesz być zmienione.
Ponieważ zadeklarowanie klasy nie uniemożliwia utworzenia instancji klasy, nie oznacza to, że powstrzyma ona klasę od posiadania właściwości obiektu. Trzeba tylko trzymać się metod dokładnie tak, jak są zadeklarowane w klasie.
źródło
myślę, że FINAL to „koniec linii” - ten facet nie może już produkować potomstwa. Więc kiedy spojrzysz na to w ten sposób, zobaczysz mnóstwo scenariuszy ze świata rzeczywistego, które napotkasz, a będziesz musiał oznaczyć klasę znacznikiem „końca linii”. Jest to projekt oparty na domenie - jeśli twoja domena wymaga, aby dana ENTITY (klasa) nie mogła tworzyć podklas, oznacz ją jako FINAL.
Powinienem zauważyć, że nic nie powstrzymuje cię przed odziedziczeniem klasy „należy oznaczyć jako ostateczną”. Ale jest to ogólnie klasyfikowane jako „nadużycie dziedziczenia” i dzieje się tak, ponieważ najczęściej chciałbyś odziedziczyć jakąś funkcję z klasy podstawowej w swojej klasie.
Najlepszym podejściem jest przyjrzenie się domenie i pozwolenie, by podyktowało twoje decyzje projektowe.
źródło
Jak powiedziano powyżej, jeśli chcesz, aby nikt nie mógł zmienić funkcjonalności metody, możesz zadeklarować ją jako ostateczną.
Przykład: Ścieżka pliku serwera aplikacji do pobierania / wysyłania, podział łańcucha na podstawie przesunięcia, takie metody można zadeklarować jako końcowe, aby te funkcje metod nie uległy zmianie. A jeśli chcesz takich metod końcowych w osobnej klasie, zdefiniuj tę klasę jako klasę końcową. Tak więc klasa końcowa będzie miała wszystkie metody końcowe, przy czym jako metoda końcowa może być zadeklarowana i zdefiniowana w klasie niefunkcjonalnej.
źródło
Klasa Android Looper jest dobrym tego praktycznym przykładem. http://developer.android.com/reference/android/os/Looper.html
Klasa Looper zapewnia pewną funkcjonalność, która NIE ma być nadpisywana przez żadną inną klasę. Dlatego nie ma tu żadnej podklasy.
źródło
Powiedzmy, że masz
Employee
klasę, która ma metodęgreet
. Pogreet
wywołaniu metody po prostu drukujeHello everyone!
. Więc to jest oczekiwane zachowanie odgreet
metodyTeraz pozwól, aby
GrumpyEmployee
podklasaEmployee
igreet
metoda zastąpiły , jak pokazano poniżej.Teraz w poniższym kodzie spójrz na
sayHello
metodę. PobieraEmployee
instancję jako parametr i wywołuje metodę powitania z nadzieją, że powie:Hello everyone!
Ale dostajemy toGet lost!
. Ta zmiana zachowania wynika zEmployee grumpyEmployee = new GrumpyEmployee();
Tej sytuacji można uniknąć, jeśli
Employee
klasa została stworzonafinal
. Wyobraź sobie, jaki chaos może wywołać bezczelny programista, jeśliString
Class nie zostanie zadeklarowany jakofinal
.źródło
Klasy końcowej nie można dalej przedłużać. Jeśli nie musimy uczynić klasy dziedziczoną w Javie, możemy zastosować to podejście.
Jeśli musimy po prostu stworzyć określone metody w klasie, aby ich nie zastąpić, możemy po prostu umieścić przed nimi końcowe słowo kluczowe. Tam klasa jest nadal dziedziczna.
źródło
Orientacja obiektowa nie polega na dziedziczeniu, chodzi o enkapsulację. Dziedziczenie przerywa enkapsulację.
W wielu przypadkach ogłoszenie finału klasy ma sens. Każdy przedmiot reprezentujący „wartość”, taki jak kolor lub kwota pieniężna, może być ostateczny. Stają na własną rękę.
Jeśli piszesz biblioteki, spraw, aby twoje zajęcia były ostateczne, chyba że wyraźnie włączysz je, aby je wyprowadzić. W przeciwnym razie ludzie mogą wywnioskować twoje klasy i zastąpić metody, łamiąc twoje założenia / niezmienniki. Może to mieć również wpływ na bezpieczeństwo.
Joshua Bloch w „Skutecznej Javie” zaleca jawne projektowanie dziedziczenia lub zabranianie go i zauważa, że projektowanie dziedziczenia nie jest takie łatwe.
źródło