Używanie modyfikatora „końcowego”, jeśli dotyczy Java [zamknięte]
194
W Javie istnieje praktyka deklarowania każdej zmiennej (lokalnej lub klasy), parametru końcowego, jeśli tak naprawdę jest.
Chociaż czyni to kod bardziej szczegółowym, pomaga to w łatwym czytaniu / uchwyceniu kodu, a także zapobiega błędom, ponieważ intencja jest wyraźnie zaznaczona.
Może to prowadzić do dyskusji religijnej. Niektórzy to lubią, niektórzy go nie znoszą. Lubię końcowe pola, ale nie końcowe zmienne lokalne, chyba że muszą być, nie jestem pewien, czy jest to całkowicie racjonalne. Nie jestem pewien, czy głosowanie w głosowaniu negatywnym byłoby. Zgadzam się z Alexem Millerem. ;)
Myślę, że to wszystko ma związek z dobrym stylem kodowania. Oczywiście możesz pisać dobre, solidne programy bez użycia wielu finalmodyfikatorów w dowolnym miejscu, ale kiedy o tym pomyślisz ...
Dodanie finaldo wszystkich rzeczy, które nie powinny się zmienić, po prostu zawęża możliwości, że ty (lub następny programista pracujący nad twoim kodem) źle zinterpretujesz lub niewłaściwie wykorzystasz proces myślowy, który spowodował twój kod. Przynajmniej powinien zadzwonić kilkoma dzwonkami, kiedy będą chcieli zmienić twoją wcześniej niezmienną rzecz.
Na początku trochę dziwnie jest widzieć wiele finalsłów kluczowych w kodzie, ale wkrótce przestaniesz zauważać samo słowo i po prostu pomyślisz, że to, co nigdy nie zmieni się od tego punktu na (możesz mi to zabrać ;-)
Myślę, że to dobra praktyka. Nie używam tego przez cały czas, ale kiedy mogę i sensowne jest oznaczenie czegoś final, zrobię to.
Zamiast używać końcowego słowa kluczowego do parametrów, można użyć narzędzia analizy statycznej, takiego jak FindBugs, aby wymagać, aby zmienne parametrów nie były ponownie przypisywane. W ten sposób usuwasz obciążenie składniowe i możesz je wymusić za pomocą kontroli FindBugs w narzędziu Ciągłej integracji.
Timo Westkämper
20
@ Timo To zadziałałoby, ale ma tę wadę, że należy to sprawdzić po zameldowaniu, a nie podczas, gdy programista pracuje nad kodem. Ponieważ finalkompilator oczywiście nie pozwoli ci kontynuować, jeśli popełnisz błąd.
Mike
9
Zaćmienie ma opcję dodania finalzawsze możliwego (zmienne, które się nie zmieniają) za każdym razem, gdy zapisujesz.
Bert F,
22
+1 kocham final. Nie robi to różnicy 98% czasu, jest to drobna niedogodność% 1 czasu, ale 1% czasu oszczędza mi robienia czegoś głupiego lub niezamierzonego, jest tego warte.
Bert F
14
@BertF Tak, zawsze pozwalam Eclipse na dodawanie finalmodyfikatorów wszędzie, kiedy „Oczyszczam ...” mój kod. Wszędzie znaczy nawet w blokach catch () i, jak powiedziano, po pewnym czasie ich nie zauważysz. Oczywiście, gdybym utworzył język, finalbyłoby to domyślne, a a varlub - modifiableopcjonalne słowo kluczowe.
Maarten Bodewes,
191
Obsesja na punkcie:
Pola końcowe - Oznaczenie pól jako końcowe zmusza je do ustawienia do końca budowy, dzięki czemu to pole odniesienia pozostaje niezmienne. Umożliwia to bezpieczną publikację pól i pozwala uniknąć konieczności synchronizacji przy późniejszych odczytach. (Należy zauważyć, że w przypadku odwołania do obiektu tylko odwołanie do pola jest niezmienne - rzeczy, do których odwołuje się odwołanie do obiektu, mogą się nadal zmieniać, co wpływa na niezmienność).
Końcowe pola statyczne - chociaż teraz używam wyliczeń w wielu przypadkach, w których używałem statycznych pól końcowych.
Zastanów się, ale używaj rozsądnie:
Klasy końcowe - Projekt / Framework to jedyny przypadek, w którym go rozważam.
Metody końcowe - Zasadniczo takie same jak klasy końcowe. Jeśli używasz wzorców metod szablonów, takich jak szalone i oznaczanie rzeczy jako ostatecznych, prawdopodobnie zbytnio polegasz na dziedziczeniu, a za mało na delegowaniu.
Ignoruj, chyba że czujesz się analny:
Parametry metody i zmienne lokalne - RZADKO robię to głównie dlatego, że jestem leniwy i uważam, że zaśmieca kod. Przyznaję w pełni, że oznaczanie parametrów i zmiennych lokalnych, których nie zamierzam modyfikować, jest „jaśniejsze”. Chciałbym, żeby to była wartość domyślna. Ale tak nie jest i trudno mi zrozumieć kod w finałach. Jeśli jestem w czyimś kodzie, nie zamierzam go wyciągać, ale jeśli piszę nowy kod, nie wstawię go. Jednym wyjątkiem jest sytuacja, w której musisz zaznaczyć coś ostatecznego, abyś mógł uzyskać do niego dostęp z anonimowej klasy wewnętrznej.
najlepsza jak dotąd odpowiedź na wiele pytań na ten ostatni temat
Gabriel Ščerbák
4
Przez większość czasu, gdy widzę zmienną lokalną bez ostatniego słowa przed nią i nie można jej tam użyć, mówi mi, że prawdopodobnie powinienem wyodrębnić trochę kodu w nowej metodzie, która zwraca pożądaną wartość, którą skończę. Przypadki, w których nie ma to zastosowania, mają miejsce, gdy korzystam z niektórych strumieni lub też trzeba spróbować je złapać.
nyxz,
32
Naprawdę musisz zrozumieć pełne wykorzystanie końcowego słowa kluczowego przed jego użyciem. Może mieć zastosowanie i ma różny wpływ na zmienne, pola, metody i klasy
Polecam sprawdzenie artykułu, do którego link znajduje się poniżej, aby uzyskać więcej informacji.
finalModyfikator, zwłaszcza dla zmiennych, jest środkiem mieć kompilator egzekwowania konwencji, która jest ogólnie sensowne: upewnij się, że zmienna a (lokalny lub instancja) jest przypisany dokładnie jeden raz (nie więcej nie mniej). Upewniając się, że zmienna jest zdecydowanie przypisana przed użyciem, można uniknąć typowych przypadków NullPointerException:
finalFileInputStream in;if(test)
in =newFileInputStream("foo.txt");elseSystem.out.println("test failed");
in.read();// Compiler error because variable 'in' might be unassigned
Zapobiegając przypisywaniu zmiennej więcej niż raz, odradzasz określanie zasięgu za granicą. Zamiast tego:
String msg =null;for(int i =0; i <10; i++){
msg ="We are at position "+ i;System.out.println(msg);}
msg =null;
Zachęcamy do korzystania z tego:
for(int i =0; i <10; i++){finalString msg ="We are at position "+ i;System.out.println(msg);}
Właściwie „Upewniając się, że zmienna jest definitywnie przypisana przed jej użyciem, można uniknąć typowych przypadków wyjątku NullPointerException:„ to nie jest poprawne, „końcowy” nie ma tutaj znaczenia, kompilator wie i może narzekać na zmienną „in” w podanym przykładzie jest zerowy.
nyholku
@nyholku Masz rację, w Javie zmienne lokalne muszą zostać definitywnie przypisane przed użyciem, także bez ostatecznego. Ale w przypadku pól potrzebujesz finału. W nieco bardziej złożonym przykładzie, w którym „in” jest zmienną instancji klasy, a jeśli / else jest w konstruktorze, potrzebny jest ostatni, aby zasygnalizować problem. Co więcej, również dla zmiennych lokalnych jest pewna wartość w końcowym IMO, ponieważ uniemożliwia to niechlujnemu programistowi „naprawienie” błędu kompilacji związanego z możliwością „nieprzypisania” przez dodanie „= null” do deklaracji. Innymi słowy, z mojego doświadczenia wynika, że zmienne końcowe ograniczają użycie wartości null.
Bruno De Fraine
20
Jestem dość dogmatyczny w kwestii deklarowania każdej możliwej zmiennej final. Obejmuje to parametry metody, zmienne lokalne i rzadko pola wartości. Mam trzy główne powody, dla których wszędzie deklaruję zmienne końcowe:
Deklarowanie intencji: Deklarując zmienną końcową, stwierdzam, że zmienna ta ma być zapisana tylko raz. Jest to subtelna wskazówka dla innych programistów i duża wskazówka dla kompilatora.
Egzekwowanie zmiennych jednorazowego użytku: Wierzę w ideę, że każda zmienna powinna mieć tylko jeden cel w życiu. Dając każdej zmiennej tylko jeden cel, zmniejszasz czas potrzebny na sprawdzenie celu tej konkretnej zmiennej podczas debugowania.
Zezwala na optymalizację: wiem, że kompilator miał kiedyś sztuczki zwiększające wydajność, które polegały w szczególności na niezmienności zmiennej odniesienia. Lubię myśleć, że niektóre z tych starych sztuczek związanych z wydajnością (lub nowe) zostaną wykorzystane przez kompilator.
Myślę jednak, że końcowe klasy i metody nie są tak przydatne, jak odwołania do zmiennych końcowych. Słowo finalkluczowe użyte w tych deklaracjach po prostu zapewnia przeszkody w automatycznym testowaniu i wykorzystaniu kodu w sposób, którego nigdy nie można było się spodziewać.
finalzmienne i parametry metody nie mają wpływu na wydajność, ponieważ nie jest wyrażony w kodzie bajtowym.
Steve Kuo
zmienna: = łacina: varius> różne> modyfikowalne
dieter
17
Skuteczna Java zawiera element z napisem „Preferuj niezmienne obiekty”. Uznanie pól za ostateczne pomaga zrobić kilka małych kroków w tym kierunku, ale w przypadku obiektów naprawdę niezmiennych jest znacznie więcej.
Jeśli wiesz, że obiekty są niezmienne, można je udostępnić do odczytu wielu wątkom / klientom bez obaw o synchronizację, i łatwiej jest zrozumieć, jak działa program.
ostrożny - ostateczne i niezmienne to zupełnie inne pojęcia. Łatwo jest mieć końcowy obiekt, który można modyfikować - finał dotyczy odniesienia, zmienność dotyczy instancji obiektu. ostatnia osoba olaf = nowa osoba (); olaf.setName („Olaf”);
Olaf Kock,
1
Dokładnie - niezmienne obiekty są jedną rzeczą, niezmienne odniesienia (tj. Końcowe) są czymś zupełnie innym.
SCdF,
2
Są one jednak ściśle powiązane, ponieważ można zadeklarować pole Person.name jako final (i ogłaszając klasę final, i ...) uczynić obiekt Person ostatecznym. Nie jest to jednak tak proste, jak robienie „ostatecznej osoby” ...
Sebastian Ganslandt,
Jest to również nieistotne dla zmiennych lokalnych (parametry są lokalnymi). Dotyczy to tylko zmiennych klas, więc tylko częściowo odpowiada na pytanie.
Robin,
12
Nigdy nie byłem w sytuacji, w której ostatnie słowo kluczowe na zmiennej powstrzymywało mnie od popełnienia błędu, więc na chwilę obecną myślę, że to wielka strata czasu.
Chyba że istnieje prawdziwy powód, aby to zrobić (jak w przypadku, gdy chcesz podkreślić konkretną zmienność będącą ostateczną), wolałbym tego nie robić, ponieważ uważam, że kod jest mniej czytelny.
Jeśli jednak nie okaże się, że kod ten jest trudniejszy do odczytania lub dłuższy do napisania, to na pewno idź.
Edycja: Jako wyjaśnienie (i próba odzyskania głosów niższych), nie mówię, nie oznaczaj stałych jako ostatecznych, mówię, nie rób rzeczy takich jak:
publicString doSomething(){finalString first = someReallyComplicatedExpressionToGetTheString();finalString second = anotherReallyComplicatedExpressionToGetAnother();return first+second;}
To sprawia, że kod (moim zdaniem) jest trudniejszy do odczytania.
Warto również pamiętać, że wszystko, co robi, uniemożliwia zmianę przypisania zmiennej, nie czyni jej niezmiennym ani nic podobnego.
Obrócenie oświadczenie na głowie: byłem w mnóstwo sytuacji, w których nie używając final(i niezmienne obiekty w ogóle) ma znaczący czynnik przyczyniający się do liczby i skutków błędów.
Chris Vest
3
Jestem za niezmiennymi przedmiotami, po prostu nigdy nie byłem w sytuacji, w której oznaczenie ostatecznego niezmiennego obiektu pomogło mi.
SCdF,
2
Zgadzam się, że nie powinniśmy używać ostatecznych zmiennych lokalnych i parametrów metody, ponieważ znacznie zmniejsza to czytelność kodu.
rmaruszewski
@ChrisVest, może twoje funkcje są za długie
Pacerier
8
Ostateczny należy zawsze stosować dla stałych. Przydaje się nawet w przypadku zmiennych krótkotrwałych (w ramach jednej metody), gdy zasady definiowania zmiennej są skomplikowane.
Wydaje się, że jednym z największych argumentów przeciwko używaniu końcowego słowa kluczowego jest to, że „jest to niepotrzebne” i „marnuje miejsce”.
Jeśli uznamy wiele zalet „końcowego”, jak wskazano w wielu świetnych postach tutaj, przyznając, że wymaga to więcej pisania i spacji, argumentowałbym, że Java powinna była domyślnie ustawić zmienne „końcowe” i wymagać, aby rzeczy były oznaczone „ mutable ”, jeśli programista tego chce.
To jest doskonałe. Nie ma argumentów przeciwko finaltemu, że „zbyt długo pisać”, „sprawia, że kod jest nieporadny”. Istnieje kilka argumentów za final. I możemy automatycznie dodać go przy zapisie, jeśli nie chcesz pisać ręcznie.
Dmitriy Popov
5
finalCały czas używam atrybutów obiektów.
Słowo finalkluczowe ma semantykę widoczności, gdy jest używane w przypadku atrybutów obiektu. Zasadniczo ustawienie wartości ostatecznego atrybutu obiektu ma miejsce przed powrotem konstruktora. Oznacza to, że dopóki nie pozwolisz, by thisreferencja uciekła od konstruktora i używasz finaldo wszystkich swoich atrybutów, twój obiekt (zgodnie z semantyką Java 5) jest prawidłowo skonstruowany, a ponieważ jest niezmienny, może być bezpiecznie opublikowany do innych wątków.
Niezmienne przedmioty to nie tylko bezpieczeństwo nitek. Ułatwiają także rozumowanie zmian stanu w twoim programie, ponieważ przestrzeń tego, co można zmienić, jest celowo i, jeśli jest konsekwentnie używana, całkowicie ograniczona do rzeczy, które powinny się zmienić.
Czasami też uznaję metody za ostateczne, ale nie tak często. Rzadko kończę zajęcia. Zazwyczaj robię to, ponieważ nie mam takiej potrzeby. Zazwyczaj nie używam dziedziczenia zbyt często. Wolę zamiast tego używać interfejsów i kompozycji obiektów - nadaje się to również do projektu, który moim zdaniem jest często łatwiejszy do przetestowania. Kiedy kodujesz interfejsy zamiast konkretnych klas, nie musisz używać dziedziczenia podczas testowania, w takiej formie, w ramach takich jak jMock, znacznie łatwiej jest tworzyć obiekty próbne z interfejsami niż w przypadku klas konkretnych.
Wydaje mi się, że większość zajęć powinienem zakończyć, ale po prostu jeszcze nie przyzwyczaiłem się.
Muszę przeczytać dużo kodu do mojej pracy. Brak końcowych zmiennych instancji jest jedną z najważniejszych rzeczy, które mnie denerwują i sprawiają, że zrozumienie kodu jest niepotrzebnie trudne. Za moje pieniądze, końcowe zmienne lokalne powodują więcej bałaganu niż przejrzystości. Język powinien zostać zaprojektowany tak, aby był domyślny, ale musimy żyć z pomyłką. Czasami przydaje się to szczególnie w przypadku pętli i określonego przypisania z drzewem if-else, ale przeważnie wskazuje, że twoja metoda jest zbyt skomplikowana.
Dlaczego nie skorzystać z narzędzia, które zmniejsza bałagan?
Pacerier
@Pacerier Jak w edytorze, który wprowadza w błąd w kodzie?
Tom Hawtin - tackline
3
Ostatecznie należy oczywiście stosować na stałe i aby wymusić niezmienność, ale jest też inne ważne zastosowanie metod.
Skuteczna Java zawiera w tym cały przedmiot (punkt 15), wskazujący pułapki niezamierzonego dziedziczenia. Skutecznie, jeśli nie zaprojektowałeś i nie udokumentowałeś swojej klasy do dziedziczenia, dziedziczenie po niej może dać nieoczekiwane problemy (przedmiot daje dobry przykład). Dlatego zaleca się, abyś używał finału na dowolnej klasie i / lub metodzie, z której nie zamierzano dziedziczyć.
To może wydawać się drakońskie, ale ma sens. Jeśli piszesz bibliotekę klas do użytku przez innych, nie chcesz, aby dziedziczyły po rzeczach, które nie zostały do niej zaprojektowane - zablokujesz się w konkretnej implementacji klasy dla kompatybilności wstecznej. Jeśli kodujesz w zespole, nic nie stoi na przeszkodzie, aby inny członek zespołu usunął finał, jeśli naprawdę musi. Ale słowo kluczowe zmusza ich do zastanowienia się nad tym, co robią i ostrzega ich, że klasa, od której dziedziczą, nie została do tego zaprojektowana, dlatego powinni być bardzo ostrożni.
Kolejnym zastrzeżeniem jest to, że wiele osób myli zdanie końcowe, co oznacza, że zawartość zmiennej instancji nie może się zmienić, a nie, że odwołanie nie może się zmienić.
Nawet w przypadku zmiennych lokalnych wiedza, że jest ona deklarowana jako ostateczna, oznacza, że nie muszę się martwić, że odwołanie zostanie zmienione później. Oznacza to, że podczas debugowania i później widzę tę zmienną, jestem pewien, że odnosi się do tego samego obiektu. To jedna rzecz, o którą muszę się martwić, szukając błędu. Dodatkową korzyścią jest to, że jeśli 99% zmiennych zostanie uznanych za ostateczne, to kilka zmiennych, które naprawdę są zmiennymi, lepiej się wyróżnia. Ponadto finał pozwala kompilatorowi znaleźć jeszcze więcej głupich błędów, które w przeciwnym razie mogłyby pozostać niezauważone.
Końcowy, gdy jest używany ze zmiennymi w Javie, zastępuje stałą w C ++. Kiedy więc zmienna końcowa i statyczna zostanie użyta dla zmiennej, staje się ona niezmienna. Jednocześnie sprawia, że migrowani programiści C ++ są bardzo szczęśliwi ;-)
W przypadku użycia ze zmiennymi odniesienia nie pozwala na ponowne odniesienie do obiektu, chociaż obiektem można manipulować.
W przypadku użycia metody końcowej metoda nie pozwala na przesłonięcie metody przez podklasy.
Gdy użycie jest bardzo jasne, należy z niego korzystać ostrożnie. Zależy to głównie od projektu, ponieważ użycie metody końcowej w metodzie nie pomogłoby polimorfizmowi.
Należy go używać tylko w przypadku zmiennych, gdy masz cholerną pewność, że wartość zmiennej nigdy nie powinna zostać zmieniona. Upewnij się także, że przestrzegasz konwencji kodowania zalecanej przez SUN. Na przykład: final int COLOR_RED = 1; (Wielkie litery oddzielone znakiem podkreślenia)
Ze zmienną referencyjną używaj jej tylko wtedy, gdy potrzebujemy niezmiennego odwołania do konkretnego obiektu.
Jeśli chodzi o część dotyczącą czytelności, upewnij się, że komentarze odgrywają bardzo ważną rolę podczas używania końcowego modyfikatora.
Czy ktoś może mi powiedzieć, dlaczego jest to przegłosowane? Po prostu ciekawy ..
Omnipotent
Jest tak prawdopodobnie dlatego, że twierdzisz, że powinieneś zrobić to WYŁĄCZNIE, gdy XYZ. Inni uważają, że lepszą praktyką jest, aby WSZYSTKO było ostateczne, chyba że zachodzi taka potrzeba.
Outlaw Programmer
1
W ogóle nie zastępuje słowa kluczowego const C ++. -1.
tmj
1
Nigdy nie używam ich w zmiennych lokalnych, dodanie gadatliwości nie ma sensu. Nawet jeśli nie uważasz, że zmienna powinna zostać ponownie przypisana, nie będzie to miało większego znaczenia dla następnej osoby zmieniającej kod, który myśli inaczej, a ponieważ kod jest zmieniany, każdy pierwotny cel, aby był ostateczny, może już nie być prawidłowy. Jeśli chodzi tylko o jasność, uważam, że zawodzi z powodu negatywnych skutków gadatliwości.
Prawie to samo dotyczy również zmiennych składowych, ponieważ zapewniają one niewielką korzyść, z wyjątkiem przypadku stałych.
Nie ma również wpływu na niezmienność, ponieważ najlepszym wskaźnikiem niezmienności jest to, że jest udokumentowane jako takie i / lub nie ma metod, które mogłyby zmienić obiekt (to, wraz z uczynieniem klasy ostateczną, jest jedynym sposobem na zagwarantowanie, że jest niezmienny).
Skonfigurowałem Eclipse, aby dodać finał do wszystkich pól i atrybutów, które nie są modyfikowane. Działa to doskonale przy użyciu „akcji zapisywania” Eclipse, która dodaje te ostatnie modyfikatory (między innymi) podczas zapisywania pliku.
W przypadku argumentów uważam, że nie są potrzebne. Mostley po prostu zranili gotowość. Ponowne przypisanie zmiennej argumentu jest tak szalenie głupie, że powinienem być całkiem pewny, że i tak można je traktować jako stałe.
Fakt, że Eclipse barwi końcową czerwień, ułatwia dostrzeżenie zmiennych deklaracji w kodzie, co moim zdaniem poprawia zdolność odczytu w większości przypadków.
Staram się egzekwować zasadę, że wszystkie zmienne powinny być ostateczne, ponieważ nie ma wyjątkowo ważnego powodu, aby tego nie robić. O wiele łatwiej jest odpowiedzieć na pytanie „co to za zmienna?” pytaj, czy po prostu musisz znaleźć inicjalizację i mieć pewność, że to jest to.
Właściwie denerwuję się wokół zmiennych niekończących już teraz. To jak różnica między tym, że nóż wisi nad nitką nad głową, a szufladą kuchenną ...
Ostatnia zmienna jest po prostu dobrym sposobem na wartości etykiety.
Nieokreślona zmienna jest związana z częścią algorytmu podatnego na błędy.
Jedną z fajnych cech jest to, że gdy opcja nie wymaga odpowiedzi dla algorytmu przez większość czasu, rozwiązaniem jest napisanie metody, co zwykle znacznie poprawia kod.
Od jakiegoś czasu programuję i używam finału, kiedy tylko mogę. Po zrobieniu tego przez chwilę (dla zmiennych, parametrów metody i atrybutów klasy) mogę powiedzieć, że 90% (lub więcej) moich zmiennych jest w rzeczywistości ostatecznych. Myślę, że korzyścią z faktu, że NIE zmieniono zmiennych, gdy nie chcesz (widziałem to wcześniej i czasami jest to ból), płaci się za dodatkowe pisanie i dodatkowe „końcowe” słowa kluczowe w kodzie.
Biorąc to pod uwagę, gdybym zaprojektował język, ustawiłbym każdą zmienną na końcową, chyba że zostałby zmodyfikowany przez inne słowo kluczowe.
Pomyślałem, że nie używam finału do zajęć i metod. Jest to mniej lub bardziej skomplikowany wybór projektu, chyba że twoja klasa jest klasą użyteczności (w takim przypadku powinieneś mieć tylko jednego prywatnego konstruktora).
Korzystam również z Collections.unmodifiable ... do tworzenia list niemodyfikowalnych, kiedy jest to konieczne.
Używanie anonimowych klas lokalnych dla detektorów zdarzeń i taki jest powszechny wzorzec w Javie. Najczęstszym zastosowaniem końcowego słowa kluczowego jest upewnienie się, że zmienne w zakresie są dostępne dla parzystego słuchacza.
Jeśli jednak będziesz musiał umieścić w swoim kodzie wiele końcowych instrukcji. To może być dobra wskazówka, że robisz coś źle.
Artykuł opublikowany powyżej podaje ten przykład:
publicvoid doSomething(int i,int j){finalint n = i + j;// must be declared finalComparator comp =newComparator(){publicint compare(Object left,Object right){return n;// return copy of a local variable}};}
Używam go do stałych wewnątrz i na zewnątrz metod.
Czasami używam go do metod, ponieważ nie wiem, czy podklasa NIE chciałaby zastąpić danej metody (z jakichkolwiek powodów).
Jeśli chodzi o klasy, tylko dla niektórych klas infrastruktury użyłem klasy ostatecznej.
IntelliJ IDEA ostrzega, jeśli parametr funkcji jest zapisany w funkcji. Przestałem więc używać argumentu funkcji końcowej. Nie widzę ich również w bibliotece Java Runtime.
Hmm .. edytowane w jednym miejscu .. nadal mówi się w końcu na drugiej linii ;-)
Omnipotent
Umożliwienie ludziom nadpisywania wartości jest jedynym największym źródłem niespodzianek i trudnych do wykrycia błędów
RAY
0
Oznaczenie klasy końcowej może również powodować, że niektóre wiązania metod będą się pojawiać w czasie kompilacji zamiast w środowisku wykonawczym. Rozważmy „v2.foo ()” poniżej - kompilator wie, że B nie może mieć podklasy, więc nie można zastąpić foo (), więc implementacja do wywołania jest znana w czasie kompilacji. Jeśli klasa B NIE jest oznaczona jako ostateczna, możliwe jest, że faktycznym typem v2 jest klasa, która rozszerza B i zastępuje foo ().
class A {void foo(){//do something}}finalclass B extends A {void foo(){}}classTest{publicvoid t(A v1, B v2){
v1.foo();
v2.foo();}}
Zdecydowanie zachęca się do używania ostatecznego dla stałych . Nie użyłbym go jednak do metod lub klas (a przynajmniej przez chwilę o tym myślał), ponieważ utrudnia to testowanie , jeśli nie jest niemożliwe. Jeśli absolutnie musisz uczynić klasę lub metodę ostateczną, upewnij się, że ta klasa implementuje jakiś interfejs, abyś mógł mieć próbną implementację tego samego interfejsu.
Odpowiedzi:
Myślę, że to wszystko ma związek z dobrym stylem kodowania. Oczywiście możesz pisać dobre, solidne programy bez użycia wielu
final
modyfikatorów w dowolnym miejscu, ale kiedy o tym pomyślisz ...Dodanie
final
do wszystkich rzeczy, które nie powinny się zmienić, po prostu zawęża możliwości, że ty (lub następny programista pracujący nad twoim kodem) źle zinterpretujesz lub niewłaściwie wykorzystasz proces myślowy, który spowodował twój kod. Przynajmniej powinien zadzwonić kilkoma dzwonkami, kiedy będą chcieli zmienić twoją wcześniej niezmienną rzecz.Na początku trochę dziwnie jest widzieć wiele
final
słów kluczowych w kodzie, ale wkrótce przestaniesz zauważać samo słowo i po prostu pomyślisz, że to, co nigdy nie zmieni się od tego punktu na (możesz mi to zabrać ;-)Myślę, że to dobra praktyka. Nie używam tego przez cały czas, ale kiedy mogę i sensowne jest oznaczenie czegoś
final
, zrobię to.źródło
final
kompilator oczywiście nie pozwoli ci kontynuować, jeśli popełnisz błąd.final
zawsze możliwego (zmienne, które się nie zmieniają) za każdym razem, gdy zapisujesz.final
. Nie robi to różnicy 98% czasu, jest to drobna niedogodność% 1 czasu, ale 1% czasu oszczędza mi robienia czegoś głupiego lub niezamierzonego, jest tego warte.final
modyfikatorów wszędzie, kiedy „Oczyszczam ...” mój kod. Wszędzie znaczy nawet w blokach catch () i, jak powiedziano, po pewnym czasie ich nie zauważysz. Oczywiście, gdybym utworzył język,final
byłoby to domyślne, a avar
lub -modifiable
opcjonalne słowo kluczowe.Obsesja na punkcie:
Zastanów się, ale używaj rozsądnie:
Ignoruj, chyba że czujesz się analny:
źródło
Naprawdę musisz zrozumieć pełne wykorzystanie końcowego słowa kluczowego przed jego użyciem. Może mieć zastosowanie i ma różny wpływ na zmienne, pola, metody i klasy
Polecam sprawdzenie artykułu, do którego link znajduje się poniżej, aby uzyskać więcej informacji.
Ostatnie słowo Na ostatnie słowo kluczowe
źródło
final
Modyfikator, zwłaszcza dla zmiennych, jest środkiem mieć kompilator egzekwowania konwencji, która jest ogólnie sensowne: upewnij się, że zmienna a (lokalny lub instancja) jest przypisany dokładnie jeden raz (nie więcej nie mniej). Upewniając się, że zmienna jest zdecydowanie przypisana przed użyciem, można uniknąć typowych przypadkówNullPointerException
:Zapobiegając przypisywaniu zmiennej więcej niż raz, odradzasz określanie zasięgu za granicą. Zamiast tego:
Zachęcamy do korzystania z tego:
Niektóre linki:
źródło
final
, aby uczynić Javy więcej ekspresji opartej .Jestem dość dogmatyczny w kwestii deklarowania każdej możliwej zmiennej
final
. Obejmuje to parametry metody, zmienne lokalne i rzadko pola wartości. Mam trzy główne powody, dla których wszędzie deklaruję zmienne końcowe:Myślę jednak, że końcowe klasy i metody nie są tak przydatne, jak odwołania do zmiennych końcowych. Słowo
final
kluczowe użyte w tych deklaracjach po prostu zapewnia przeszkody w automatycznym testowaniu i wykorzystaniu kodu w sposób, którego nigdy nie można było się spodziewać.źródło
final
zmienne i parametry metody nie mają wpływu na wydajność, ponieważ nie jest wyrażony w kodzie bajtowym.Skuteczna Java zawiera element z napisem „Preferuj niezmienne obiekty”. Uznanie pól za ostateczne pomaga zrobić kilka małych kroków w tym kierunku, ale w przypadku obiektów naprawdę niezmiennych jest znacznie więcej.
Jeśli wiesz, że obiekty są niezmienne, można je udostępnić do odczytu wielu wątkom / klientom bez obaw o synchronizację, i łatwiej jest zrozumieć, jak działa program.
źródło
Nigdy nie byłem w sytuacji, w której ostatnie słowo kluczowe na zmiennej powstrzymywało mnie od popełnienia błędu, więc na chwilę obecną myślę, że to wielka strata czasu.
Chyba że istnieje prawdziwy powód, aby to zrobić (jak w przypadku, gdy chcesz podkreślić konkretną zmienność będącą ostateczną), wolałbym tego nie robić, ponieważ uważam, że kod jest mniej czytelny.
Jeśli jednak nie okaże się, że kod ten jest trudniejszy do odczytania lub dłuższy do napisania, to na pewno idź.
Edycja: Jako wyjaśnienie (i próba odzyskania głosów niższych), nie mówię, nie oznaczaj stałych jako ostatecznych, mówię, nie rób rzeczy takich jak:
To sprawia, że kod (moim zdaniem) jest trudniejszy do odczytania.
Warto również pamiętać, że wszystko, co robi, uniemożliwia zmianę przypisania zmiennej, nie czyni jej niezmiennym ani nic podobnego.
źródło
final
(i niezmienne obiekty w ogóle) ma znaczący czynnik przyczyniający się do liczby i skutków błędów.Ostateczny należy zawsze stosować dla stałych. Przydaje się nawet w przypadku zmiennych krótkotrwałych (w ramach jednej metody), gdy zasady definiowania zmiennej są skomplikowane.
Na przykład:
źródło
Wydaje się, że jednym z największych argumentów przeciwko używaniu końcowego słowa kluczowego jest to, że „jest to niepotrzebne” i „marnuje miejsce”.
Jeśli uznamy wiele zalet „końcowego”, jak wskazano w wielu świetnych postach tutaj, przyznając, że wymaga to więcej pisania i spacji, argumentowałbym, że Java powinna była domyślnie ustawić zmienne „końcowe” i wymagać, aby rzeczy były oznaczone „ mutable ”, jeśli programista tego chce.
źródło
final
temu, że „zbyt długo pisać”, „sprawia, że kod jest nieporadny”. Istnieje kilka argumentów zafinal
. I możemy automatycznie dodać go przy zapisie, jeśli nie chcesz pisać ręcznie.final
Cały czas używam atrybutów obiektów.Słowo
final
kluczowe ma semantykę widoczności, gdy jest używane w przypadku atrybutów obiektu. Zasadniczo ustawienie wartości ostatecznego atrybutu obiektu ma miejsce przed powrotem konstruktora. Oznacza to, że dopóki nie pozwolisz, bythis
referencja uciekła od konstruktora i używaszfinal
do wszystkich swoich atrybutów, twój obiekt (zgodnie z semantyką Java 5) jest prawidłowo skonstruowany, a ponieważ jest niezmienny, może być bezpiecznie opublikowany do innych wątków.Niezmienne przedmioty to nie tylko bezpieczeństwo nitek. Ułatwiają także rozumowanie zmian stanu w twoim programie, ponieważ przestrzeń tego, co można zmienić, jest celowo i, jeśli jest konsekwentnie używana, całkowicie ograniczona do rzeczy, które powinny się zmienić.
Czasami też uznaję metody za ostateczne, ale nie tak często. Rzadko kończę zajęcia. Zazwyczaj robię to, ponieważ nie mam takiej potrzeby. Zazwyczaj nie używam dziedziczenia zbyt często. Wolę zamiast tego używać interfejsów i kompozycji obiektów - nadaje się to również do projektu, który moim zdaniem jest często łatwiejszy do przetestowania. Kiedy kodujesz interfejsy zamiast konkretnych klas, nie musisz używać dziedziczenia podczas testowania, w takiej formie, w ramach takich jak jMock, znacznie łatwiej jest tworzyć obiekty próbne z interfejsami niż w przypadku klas konkretnych.
Wydaje mi się, że większość zajęć powinienem zakończyć, ale po prostu jeszcze nie przyzwyczaiłem się.
źródło
Muszę przeczytać dużo kodu do mojej pracy. Brak końcowych zmiennych instancji jest jedną z najważniejszych rzeczy, które mnie denerwują i sprawiają, że zrozumienie kodu jest niepotrzebnie trudne. Za moje pieniądze, końcowe zmienne lokalne powodują więcej bałaganu niż przejrzystości. Język powinien zostać zaprojektowany tak, aby był domyślny, ale musimy żyć z pomyłką. Czasami przydaje się to szczególnie w przypadku pętli i określonego przypisania z drzewem if-else, ale przeważnie wskazuje, że twoja metoda jest zbyt skomplikowana.
źródło
Ostatecznie należy oczywiście stosować na stałe i aby wymusić niezmienność, ale jest też inne ważne zastosowanie metod.
Skuteczna Java zawiera w tym cały przedmiot (punkt 15), wskazujący pułapki niezamierzonego dziedziczenia. Skutecznie, jeśli nie zaprojektowałeś i nie udokumentowałeś swojej klasy do dziedziczenia, dziedziczenie po niej może dać nieoczekiwane problemy (przedmiot daje dobry przykład). Dlatego zaleca się, abyś używał finału na dowolnej klasie i / lub metodzie, z której nie zamierzano dziedziczyć.
To może wydawać się drakońskie, ale ma sens. Jeśli piszesz bibliotekę klas do użytku przez innych, nie chcesz, aby dziedziczyły po rzeczach, które nie zostały do niej zaprojektowane - zablokujesz się w konkretnej implementacji klasy dla kompatybilności wstecznej. Jeśli kodujesz w zespole, nic nie stoi na przeszkodzie, aby inny członek zespołu usunął finał, jeśli naprawdę musi. Ale słowo kluczowe zmusza ich do zastanowienia się nad tym, co robią i ostrzega ich, że klasa, od której dziedziczą, nie została do tego zaprojektowana, dlatego powinni być bardzo ostrożni.
źródło
Kolejnym zastrzeżeniem jest to, że wiele osób myli zdanie końcowe, co oznacza, że zawartość zmiennej instancji nie może się zmienić, a nie, że odwołanie nie może się zmienić.
źródło
Nawet w przypadku zmiennych lokalnych wiedza, że jest ona deklarowana jako ostateczna, oznacza, że nie muszę się martwić, że odwołanie zostanie zmienione później. Oznacza to, że podczas debugowania i później widzę tę zmienną, jestem pewien, że odnosi się do tego samego obiektu. To jedna rzecz, o którą muszę się martwić, szukając błędu. Dodatkową korzyścią jest to, że jeśli 99% zmiennych zostanie uznanych za ostateczne, to kilka zmiennych, które naprawdę są zmiennymi, lepiej się wyróżnia. Ponadto finał pozwala kompilatorowi znaleźć jeszcze więcej głupich błędów, które w przeciwnym razie mogłyby pozostać niezauważone.
źródło
Wybór typu
final
dla każdego parametru w każdej metodzie spowoduje tak duże podrażnienie zarówno dla programistów, jak i czytników kodów.Kiedy podrażnienie wykracza poza rozsądne przejście na Scalę, gdzie argumenty są domyślnie ostateczne.
Lub zawsze możesz użyć narzędzi do stylizacji kodu, które zrobią to automatycznie. Wszystkie IDE mają je zaimplementowane lub jako wtyczki.
źródło
Końcowy, gdy jest używany ze zmiennymi w Javie, zastępuje stałą w C ++. Kiedy więc zmienna końcowa i statyczna zostanie użyta dla zmiennej, staje się ona niezmienna. Jednocześnie sprawia, że migrowani programiści C ++ są bardzo szczęśliwi ;-)
W przypadku użycia ze zmiennymi odniesienia nie pozwala na ponowne odniesienie do obiektu, chociaż obiektem można manipulować.
W przypadku użycia metody końcowej metoda nie pozwala na przesłonięcie metody przez podklasy.
Gdy użycie jest bardzo jasne, należy z niego korzystać ostrożnie. Zależy to głównie od projektu, ponieważ użycie metody końcowej w metodzie nie pomogłoby polimorfizmowi.
Należy go używać tylko w przypadku zmiennych, gdy masz cholerną pewność, że wartość zmiennej nigdy nie powinna zostać zmieniona. Upewnij się także, że przestrzegasz konwencji kodowania zalecanej przez SUN. Na przykład: final int COLOR_RED = 1; (Wielkie litery oddzielone znakiem podkreślenia)
Ze zmienną referencyjną używaj jej tylko wtedy, gdy potrzebujemy niezmiennego odwołania do konkretnego obiektu.
Jeśli chodzi o część dotyczącą czytelności, upewnij się, że komentarze odgrywają bardzo ważną rolę podczas używania końcowego modyfikatora.
źródło
Nigdy nie używam ich w zmiennych lokalnych, dodanie gadatliwości nie ma sensu. Nawet jeśli nie uważasz, że zmienna powinna zostać ponownie przypisana, nie będzie to miało większego znaczenia dla następnej osoby zmieniającej kod, który myśli inaczej, a ponieważ kod jest zmieniany, każdy pierwotny cel, aby był ostateczny, może już nie być prawidłowy. Jeśli chodzi tylko o jasność, uważam, że zawodzi z powodu negatywnych skutków gadatliwości.
Prawie to samo dotyczy również zmiennych składowych, ponieważ zapewniają one niewielką korzyść, z wyjątkiem przypadku stałych.
Nie ma również wpływu na niezmienność, ponieważ najlepszym wskaźnikiem niezmienności jest to, że jest udokumentowane jako takie i / lub nie ma metod, które mogłyby zmienić obiekt (to, wraz z uczynieniem klasy ostateczną, jest jedynym sposobem na zagwarantowanie, że jest niezmienny).
Ale hej, to tylko moja opinia :-)
źródło
Skonfigurowałem Eclipse, aby dodać finał do wszystkich pól i atrybutów, które nie są modyfikowane. Działa to doskonale przy użyciu „akcji zapisywania” Eclipse, która dodaje te ostatnie modyfikatory (między innymi) podczas zapisywania pliku.
Wysoce rekomendowane.
Sprawdź mój wpis na blogu dotyczący akcji zapisywania Eclipse.
źródło
W przypadku argumentów uważam, że nie są potrzebne. Mostley po prostu zranili gotowość. Ponowne przypisanie zmiennej argumentu jest tak szalenie głupie, że powinienem być całkiem pewny, że i tak można je traktować jako stałe.
Fakt, że Eclipse barwi końcową czerwień, ułatwia dostrzeżenie zmiennych deklaracji w kodzie, co moim zdaniem poprawia zdolność odczytu w większości przypadków.
Staram się egzekwować zasadę, że wszystkie zmienne powinny być ostateczne, ponieważ nie ma wyjątkowo ważnego powodu, aby tego nie robić. O wiele łatwiej jest odpowiedzieć na pytanie „co to za zmienna?” pytaj, czy po prostu musisz znaleźć inicjalizację i mieć pewność, że to jest to.
Właściwie denerwuję się wokół zmiennych niekończących już teraz. To jak różnica między tym, że nóż wisi nad nitką nad głową, a szufladą kuchenną ...
Ostatnia zmienna jest po prostu dobrym sposobem na wartości etykiety.
Nieokreślona zmienna jest związana z częścią algorytmu podatnego na błędy.
Jedną z fajnych cech jest to, że gdy opcja nie wymaga odpowiedzi dla algorytmu przez większość czasu, rozwiązaniem jest napisanie metody, co zwykle znacznie poprawia kod.
źródło
Od jakiegoś czasu programuję i używam finału, kiedy tylko mogę. Po zrobieniu tego przez chwilę (dla zmiennych, parametrów metody i atrybutów klasy) mogę powiedzieć, że 90% (lub więcej) moich zmiennych jest w rzeczywistości ostatecznych. Myślę, że korzyścią z faktu, że NIE zmieniono zmiennych, gdy nie chcesz (widziałem to wcześniej i czasami jest to ból), płaci się za dodatkowe pisanie i dodatkowe „końcowe” słowa kluczowe w kodzie.
Biorąc to pod uwagę, gdybym zaprojektował język, ustawiłbym każdą zmienną na końcową, chyba że zostałby zmodyfikowany przez inne słowo kluczowe.
Pomyślałem, że nie używam finału do zajęć i metod. Jest to mniej lub bardziej skomplikowany wybór projektu, chyba że twoja klasa jest klasą użyteczności (w takim przypadku powinieneś mieć tylko jednego prywatnego konstruktora).
Korzystam również z Collections.unmodifiable ... do tworzenia list niemodyfikowalnych, kiedy jest to konieczne.
źródło
Używanie anonimowych klas lokalnych dla detektorów zdarzeń i taki jest powszechny wzorzec w Javie. Najczęstszym zastosowaniem końcowego słowa kluczowego jest upewnienie się, że zmienne w zakresie są dostępne dla parzystego słuchacza.
Jeśli jednak będziesz musiał umieścić w swoim kodzie wiele końcowych instrukcji. To może być dobra wskazówka, że robisz coś źle.
Artykuł opublikowany powyżej podaje ten przykład:
źródło
Używam go do stałych wewnątrz i na zewnątrz metod.
Czasami używam go do metod, ponieważ nie wiem, czy podklasa NIE chciałaby zastąpić danej metody (z jakichkolwiek powodów).
Jeśli chodzi o klasy, tylko dla niektórych klas infrastruktury użyłem klasy ostatecznej.
IntelliJ IDEA ostrzega, jeśli parametr funkcji jest zapisany w funkcji. Przestałem więc używać argumentu funkcji końcowej. Nie widzę ich również w bibliotece Java Runtime.
źródło
Prawie nie używam finału na metodach lub zajęciach, ponieważ lubię pozwalać ludziom je przesłonić.
W przeciwnym razie używam tylko, jeśli jest to
public/private static final type SOME_CONSTANT;
źródło
Oznaczenie klasy końcowej może również powodować, że niektóre wiązania metod będą się pojawiać w czasie kompilacji zamiast w środowisku wykonawczym. Rozważmy „v2.foo ()” poniżej - kompilator wie, że B nie może mieć podklasy, więc nie można zastąpić foo (), więc implementacja do wywołania jest znana w czasie kompilacji. Jeśli klasa B NIE jest oznaczona jako ostateczna, możliwe jest, że faktycznym typem v2 jest klasa, która rozszerza B i zastępuje foo ().
źródło
Zdecydowanie zachęca się do używania ostatecznego dla stałych . Nie użyłbym go jednak do metod lub klas (a przynajmniej przez chwilę o tym myślał), ponieważ utrudnia to testowanie , jeśli nie jest niemożliwe. Jeśli absolutnie musisz uczynić klasę lub metodę ostateczną, upewnij się, że ta klasa implementuje jakiś interfejs, abyś mógł mieć próbną implementację tego samego interfejsu.
źródło