Znalazłem kilka odniesień ( na przykład ), które sugerują używanie final
jak największej ilości i zastanawiam się, jakie to ważne. Dzieje się tak głównie w kontekście parametrów metod i zmiennych lokalnych, a nie ostatecznych metod lub klas. W przypadku stałych ma to oczywisty sens.
Z jednej strony kompilator może dokonać pewnych optymalizacji, a to sprawia, że intencje programisty są jaśniejsze. Z drugiej strony dodaje szczegółowości, a optymalizacje mogą być trywialne.
Czy jest to coś, o czym powinienem starać się pamiętać?
Odpowiedzi:
Obsesja na punkcie:
Rozważ, ale używaj rozważnie:
Ignoruj, chyba że czujesz anal:
Parametry metod i zmienne lokalne - RZADKO to robię głównie dlatego, że jestem leniwy i zaśmieca to kod. W pełni przyznam, że oznaczanie parametrów i zmiennych lokalnych, których nie zamierzam modyfikować, jest „trafniejsze”. Chciałbym, żeby to było domyślne. Ale tak nie jest i uważam, że kod jest trudniejszy do zrozumienia, ponieważ finały są wszędzie. Jeśli jestem w czyimś kodzie, nie zamierzam ich wyciągać, ale jeśli piszę nowy kod, nie umieszczam ich. Jedynym wyjątkiem jest sytuacja, w której musisz oznaczyć coś ostatecznego, aby mieć dostęp to z anonimowej klasy wewnętrznej.
Edycja: zwróć uwagę, że jeden przypadek użycia, w którym końcowe zmienne lokalne są w rzeczywistości bardzo przydatne, jak wspomniał @ adam-gent, to przypadek, gdy wartość zostanie przypisana zmiennej w gałęzi
if
/else
.źródło
final
domyślnie robię prawie wszystkie klasy . Możesz nie zauważyć korzyści, jeśli nie używasz prawdziwie nowoczesnego środowiska Java IDE (tj. IDEA).final
klasach / metodach. Na przykład, jeśli ostatnia metoda zadeklaruje zgłoszenie sprawdzonego wyjątku, ale nigdy go nie zgłasza, IDEA powie ci to i możesz usunąć wyjątek zthrows
klauzuli. Czasami można również znaleźć nieużywane całe metody, które można wykryć, gdy nie można ich zastąpić.Nie, jeśli używasz Eclipse, ponieważ możesz skonfigurować akcję zapisywania, aby automatycznie dodać te końcowe modyfikatory. Wtedy zyskujesz mniejszym wysiłkiem.
źródło
Korzyści wynikające z „ostatecznej wersji” w czasie opracowywania są co najmniej tak samo istotne, jak korzyści w czasie wykonywania. Informuje przyszłych redaktorów kodu o Twoich zamiarach.
Oznaczenie klasy jako „ostateczna” wskazuje, że podczas projektowania lub implementacji klasy nie podjęto żadnych wysiłków, aby z wdziękiem obsługiwać rozszerzenie. Jeśli czytelnicy mogą dokonać zmian w klasie i chcą usunąć „końcowy” modyfikator, mogą to zrobić na własne ryzyko. Do nich należy upewnienie się, że klasa będzie dobrze obsługiwać rozszerzenie.
Oznaczanie zmiennej jako „final” (i przypisywanie jej w konstruktorze) jest przydatne przy wstrzykiwaniu zależności. Wskazuje na „współpracujący” charakter zmiennej.
Oznaczanie metody jako „ostateczna” jest przydatne w klasach abstrakcyjnych. Wyraźnie określa, gdzie znajdują się punkty przedłużenia.
źródło
final
Cały czas staram się, aby Java była bardziej oparta na wyrażeniach. Zobacz warunki Java (if,else,switch
) nie są oparte na wyrażeniach, których zawsze nienawidziłem, zwłaszcza jeśli jesteś przyzwyczajony do programowania funkcjonalnego (np. ML, Scala lub Lisp).Dlatego powinieneś zawsze (IMHO) używać zmiennych końcowych podczas używania warunków.
Dam ci przykład:
Teraz Jeśli dodasz kolejną
case
instrukcję i nie ustawiszname
kompilatora, nie powiedzie się. Kompilator również zawiedzie, jeśli nie przerwiesz w każdym przypadku (ustawisz zmienną). Dzięki temu Java jest bardzo podobna do Lispalet
wyrażeń i sprawia, że kod nie jest masowo wcięty (z powodu leksykalnych zmiennych zakresu).I jak zauważył @Recurse (ale najwyraźniej -1 mnie) możesz zrobić to, co było wcześniej, bez konieczności wykonywania
String name
final
błędu kompilatora (którego nigdy nie powiedziałem, że nie możesz), ale możesz łatwo usunąć błąd kompilatora ustawiając nazwę po przełączeniu instrukcja odrzucająca semantykę wyrażenia lub gorzej zapominająca, dobreak
której nie można spowodować błędu (pomimo tego, co mówi @Recurse) bez użyciafinal
:Ze względu na nazwę ustawienia błędu (oprócz zapomnienia, do
break
którego również innego błędu) mogę teraz przypadkowo zrobić to:Ostatnia zmienna wymusza pojedynczą ocenę tego, jaka powinna być nazwa. Podobnie jak funkcja, która ma zwracaną wartość, musi zawsze zwracać wartość (ignorując wyjątki), blok przełącznika nazwy będzie musiał rozwiązać nazwę, a tym samym powiązany z tym blokiem przełącznika, co ułatwia refaktoryzację fragmentów kodu (np. Metoda Eclipe: extract) .
Powyższe w OCaml:
Do
match ... with ...
ocenia jak funkcja tj wypowiedzi. Zwróć uwagę, jak wygląda nasza instrukcja switch.Oto przykład w schemacie (rakieta lub kurczak):
źródło
else if (...)
w a,if(...)
a tym samym resetuje zmienną. Pokazałem mu, że nigdy by się to nie zdarzyło przy ostatecznej zmiennej. Zasadniczofinal
zmusza cię do przypisania zmiennej raz i tylko raz ... więc: PZnalazłem oznaczanie parametrów metod i lokalizacji, które
final
są przydatne jako pomoc w refaktoryzacji, gdy dana metoda jest niezrozumiałym bałaganem o długości kilku stron. Posypaćfinal
swobodnie, zobacz, jakie błędy „nie można przypisać do zmiennej końcowej”, które zgłasza kompilator (lub twoje IDE), i możesz po prostu odkryć, dlaczego zmienna o nazwie „data” kończy się wartością zerową, mimo że kilka (nieaktualnych) komentarzy przysięga, że może nie zdarzyło się.Następnie możesz naprawić niektóre błędy, zastępując ponownie używane zmienne nowymi zmiennymi zadeklarowanymi bliżej punktu użycia. Wtedy odkrywasz, że możesz zawinąć całe części metody w nawiasy ustalające zakres i nagle jesteś o jedno naciśnięcie klawisza IDE od "metody wyodrębniania", a twój potwór stał się bardziej zrozumiały.
Jeśli twoja metoda nie jest już nie do naprawienia wrakiem, myślę, że może być wartościowe uczynienie rzeczy ostatecznych, aby zniechęcić ludzi do przekształcenia ich we wspomniany wrak; ale jeśli jest to krótka metoda (patrz: nie nie do utrzymania), ryzykujesz dodanie dużej ilości szczegółowości. W szczególności podpisy funkcji Java są wystarczająco trudne, aby zmieścić się do 80 znaków bez dodawania kolejnych sześciu na argument!
źródło
final
przed każdym parametrem.Cóż, to wszystko zależy od twojego stylu ... jeśli LUBISZ oglądać finał, kiedy nie będziesz modyfikować zmiennej, użyj jej. Jeśli nie lubisz tego oglądać ... zostaw to.
Osobiście lubię jak najmniej szczegółowości, więc staram się unikać dodatkowych słów kluczowych, które nie są naprawdę potrzebne.
Wolę jednak języki dynamiczne, więc prawdopodobnie nie jest zaskoczeniem, że lubię unikać gadatliwości.
Więc powiedziałbym, że po prostu wybierz kierunek, w którym się skręcasz i po prostu idź za nim (niezależnie od przypadku, staraj się być konsekwentny).
Na marginesie, pracowałem nad projektami, które zarówno używają, jak i nie używają takiego wzorca, i nie widziałem różnicy w ilości błędów lub błędów ... Nie sądzę, że jest to wzór, który będzie ogromnie popraw liczbę błędów lub cokolwiek innego, ale znowu to jest styl, a jeśli lubisz wyrażać zamiar, że nie będziesz go modyfikować, to śmiało go używaj.
źródło
W parametrach przydatne jest uniknięcie przypadkowej zmiany wartości parametru i wprowadzenie subtelnego błędu. Zwykłem ignorować to zalecenie, ale po spędzeniu około 4 godzin. w okropną metodę (z setkami linii kodu i wieloma forami, zagnieżdżonymi ifs i wszelkiego rodzaju złymi praktykami) radziłbym ci to zrobić.
Oczywiście w idealnym świecie to by się nie wydarzyło, ale… cóż… czasami trzeba wspierać kod innych. :(
źródło
Jeśli piszesz aplikację, że ktoś będzie musiał czytać kod po powiedzmy 1 roku, to tak, użyj final na zmiennej, która nie powinna być ciągle modyfikowana. Robiąc to, twój kod będzie bardziej „samodokumentujący się”, a także zmniejszysz szansę innych programistów na robienie głupich rzeczy, takich jak używanie lokalnej stałej jako lokalnej zmiennej tymczasowej.
Jeśli piszesz jakiś jednorazowy kod, nie trudź się identyfikowaniem wszystkich stałych i sprawiaj, że będą ostateczne.
źródło
Będę korzystał z finału, jak tylko będę mógł. Takie postępowanie spowoduje oznaczenie, jeśli przypadkowo zmienisz pole. Ustawiłem również parametry metody na końcowe. Robiąc to, złapałem kilka błędów w kodzie, które przejąłem, kiedy próbują „ustawić” parametr, zapominając, że Java przechodzi przez wartość.
źródło
Nie jest jasne, czy jest to oczywiste, ale ostateczne ustawienie parametru metody ma wpływ tylko na jej treść. Robi NIE przekazać jakieś ciekawe informacje na temat zamiarów metody do wywołującego. Przekazywany obiekt nadal może być mutowany w metodzie (finały nie są stałymi), a zakres zmiennej mieści się w metodzie.
Odpowiadając na Twoje dokładne pytanie, nie zawracałbym sobie głowy nadaniem ostatecznej wartości instancji lub zmiennej lokalnej (w tym parametrom metody), chyba że kod tego wymagał (np. Odwołanie do zmiennej pochodzi z klasy wewnętrznej) lub wyjaśnieniem jakiejś naprawdę skomplikowanej logiki.
Na przykład zmienne, uczyniłbym je ostatecznymi, gdyby były logicznymi stałymi.
źródło
Zmienna ma wiele zastosowań
final
. Oto tylko kilkaOstateczne stałe
Można to następnie wykorzystać do innych części kodów lub uzyskać do nich dostęp inne klasy, w ten sposób, gdybyś kiedykolwiek zmienił wartość, nie musiałbyś zmieniać ich jeden po drugim.
Zmienne końcowe
W tej klasie tworzysz zmienną końcową o określonym zakresie, która dodaje prefiks do parametru environmentKey. W tym przypadku zmienna końcowa jest ostateczna tylko w zakresie wykonania, który jest inny przy każdym wykonaniu metody. Za każdym razem, gdy wprowadzana jest metoda, finał jest odtwarzany. Tak szybko, jak jest skonstruowana, nie można jej zmienić w zakresie wykonywania metody. Pozwala to naprawić zmienną w metodzie na czas jej trwania. patrz poniżej:
Ostateczne stałe
Są one szczególnie przydatne, gdy masz naprawdę długie wiersze kodów i generują błąd kompilatora, więc nie napotkasz błędu logicznego / biznesowego, gdy ktoś przypadkowo zmieni zmienne, których nie należy zmieniać.
Ostateczne kolekcje
Inny przypadek, gdy mówimy o kolekcjach, musisz ustawić je jako niemodyfikowalne.
w przeciwnym razie, jeśli nie ustawisz go jako niemodyfikowalnego:
Klasy końcowe i metody końcowe nie mogą być odpowiednio przedłużane ani nadpisywane.
EDYCJA: ABY ROZWIĄZAĆ KOŃCOWY PROBLEM KLASOWY DOTYCZĄCY ENCAPSULACJI:
Istnieją dwa sposoby, aby zakończyć klasę. Pierwszym jest użycie słowa kluczowego final w deklaracji klasy:
Drugim sposobem nadania klasy ostatecznej jest zadeklarowanie wszystkich jej konstruktorów jako prywatnych:
Oznaczanie go jako ostatecznego oszczędza kłopotów, jeśli dowiesz się, że jest to ostateczny, aby zademonstrować spojrzenie na tę klasę testu. wygląda publicznie na pierwszy rzut oka.
Niestety, ponieważ jedyny konstruktor tej klasy jest prywatny, nie jest możliwe rozszerzenie tej klasy. W przypadku klasy Test nie ma powodu, aby zajęcia były ostateczne. Klasa Test jest dobrym przykładem tego, jak niejawne klasy końcowe mogą powodować problemy.
Dlatego powinieneś oznaczyć ją jako ostateczną, gdy niejawnie ustawiasz klasę jako ostateczną, ustawiając jej konstruktor jako prywatny.
źródło
Trochę kompromisu, jak wspomniałeś, ale wolę jawne użycie czegoś ponad niejawne użycie. Pomoże to usunąć pewne niejasności dla przyszłych opiekunów kodu - nawet jeśli to tylko Ty.
źródło
Jeśli masz klasy wewnętrzne (anonimowe), a metoda musi mieć dostęp do zmiennej metody zawierającej, musisz mieć tę zmienną jako ostateczną.
Poza tym to, co powiedziałeś, jest słuszne.
źródło
Użyj
final
słowa kluczowego dla zmiennej, jeśli tworzysz tę zmienną jakoimmutable
Deklarując zmienną jako ostateczną, pomaga programistom wykluczyć ewentualne problemy z modyfikacją zmiennych w wysoce wielowątkowym środowisku.
W wydaniu Java 8 mamy jeszcze jedną koncepcję o nazwie „
effectively final variable
”. Zmienna nieostateczna może być zmienną końcową.zmienne lokalne, do których odwołuje się wyrażenie lambda, muszą być ostateczne lub faktycznie ostateczne
Aż do Java 7 nie można używać niekońcowej zmiennej lokalnej wewnątrz anonimowej klasy, ale w Javie 8 jest to możliwe
Spójrz na ten artykuł
źródło
Po pierwsze, ostatnie słowo kluczowe służy do uczynienia zmiennej stałą. Stała oznacza, że się nie zmienia. Na przykład:
Zadeklarowałbyś zmienną jako ostateczną, ponieważ centymetr na cal się nie zmienia.
Jeśli spróbujesz zastąpić ostateczną wartość, zmienna jest tym, co została zadeklarowana jako pierwsza. Na przykład:
Wystąpił błąd kompilacji, który wygląda mniej więcej tak:
Jeśli twoja zmienna nie może być zadeklarowana jako ostateczna lub jeśli nie chcesz deklarować jej jako ostatecznej, spróbuj tego:
Spowoduje to wydrukowanie:
źródło