Jaka to różnica final
między poniższym kodem. Czy jest jakaś korzyść z zadeklarowania argumentów jako final
.
public String changeTimezone( Timestamp stamp, Timezone fTz, Timezone toTz){
return ....
}
public String changeTimezone(final Timestamp stamp, final Timezone fTz,
final Timezone toTz){
return ....
}
Odpowiedzi:
Ponieważ formalny parametr metody jest zmienną lokalną, dostęp do nich można uzyskać z wewnętrznych klas anonimowych tylko wtedy, gdy są zadeklarowane jako końcowe.
Zapobiega to deklarowaniu kolejnej lokalnej zmiennej końcowej w treści metody:
void m(final int param) { new Thread(new Runnable() { public void run() { System.err.println(param); } }).start(); }
źródło
Wyciąg z ostatniego słowa ostatniego słowa kluczowego
public void doSomething(final int i, final int j) { // cannot change the value of i or j here... // any change would be visible only inside the method... }
źródło
To ostatnie uniemożliwia przypisanie nowej wartości zmiennej, co może być pomocne w wyłapywaniu literówek. Stylistycznie możesz chcieć zachować otrzymane parametry bez zmian i przypisać je tylko do zmiennych lokalnych, więc final pomogłaby narzucić ten styl.
Muszę przyznać, że rzadko pamiętam o używaniu finału do parametrów, może powinienem.
public int example(final int basicRate){ int discountRate; discountRate = basicRate - 10; // ... lots of code here if ( isGoldCustomer ) { basicRate--; // typo, we intended to say discountRate--, final catches this } // ... more code here return discountRate; }
źródło
Nie robi to dużej różnicy. To po prostu oznacza, że nie możesz pisać:
stamp = null; fTz = new ...;
ale nadal możesz napisać:
Jest to głównie wskazówka dla programisty konserwacyjnego, która podąża za Tobą, że nie zamierzasz przypisywać nowej wartości do parametru gdzieś w środku metody, gdzie nie jest to oczywiste i dlatego może powodować zamieszanie.
źródło
Ostatnie słowo kluczowe użyte dla parametrów / zmiennych w Javie oznacza odwołanie jako ostateczne. W przypadku przekazania obiektu do innej metody system tworzy kopię zmiennej referencyjnej i przekazuje ją do metody. Oznaczając nowe referencje jako ostateczne, chronisz je przed ponownym przypisaniem. Czasami jest to uważane za dobrą praktykę kodowania.
źródło
W przypadku treści tej metody
final
słowo kluczowe zapobiegnie przypadkowemu przypisaniu odwołań do argumentów, powodując błąd kompilacji w tych przypadkach (większość IDE będzie narzekać od razu). Niektórzy mogą twierdzić, żefinal
ogólne używanie, gdy tylko jest to możliwe, przyspieszy działanie, ale tak nie jest w przypadku najnowszych maszyn JVM.źródło
Dwie zalety, które widzę, są wymienione:
1 Oznaczanie argumentu metody jako ostatecznego zapobiega ponownemu przypisaniu argumentu wewnątrz metody
Z twojego przykładu
public String changeTimezone(final Timestamp stamp, final Timezone fTz, final Timezone toTz){ // THIS WILL CAUSE COMPILATION ERROR as fTz is marked as final argument fTz = Calendar.getInstance().getTimeZone(); return .. }
W skomplikowanej metodzie oznaczanie argumentów jako ostatecznych pomoże w przypadkowej interpretacji tych argumentów jako metod zmiennych lokalnych, a ponowne przypisanie ich jako kompilatora będzie oznaczać te przypadki, jak pokazano w przykładzie.
2 Przekazanie argumentu do anonimowej klasy wewnętrznej
Ponieważ formalny parametr metody jest zmienną lokalną, dostęp do nich można uzyskać z wewnętrznych klas anonimowych tylko wtedy, gdy są zadeklarowane jako końcowe.
źródło
- W przeszłości (przed Java 8 :-))
Jawne użycie słowa kluczowego „final” wpłynęło na dostępność zmiennej metody dla wewnętrznych klas anonimowych.
- W nowoczesnym języku (Java 8+) nie ma takiej potrzeby:
Java wprowadziła zmienne „efektywnie końcowe”. Zakłada się, że zmienne lokalne i parametry metod są ostateczne, jeśli kod nie implikuje zmiany wartości zmiennej. Więc jeśli widzisz takie słowo kluczowe w Java8 +, możesz założyć, że jest zbędne. Wprowadzenie „efektywnego finału” powoduje, że przy stosowaniu lambd wpisujemy mniej kodu.
źródło
To tylko konstrukcja w Javie, która pomaga zdefiniować kontrakt i trzymać się go. Podobna dyskusja tutaj: http://c2.com/cgi/wiki?JavaFinalConsideredEvil
BTW - (jak mówi twiki), oznaczanie argumentów jako ostatecznych jest generalnie zbędne, jeśli postępujesz zgodnie z dobrymi zasadami programowania i wykonałeś ponowne przypisanie / przedefiniowanie przychodzącego odwołania do argumentu.
W najgorszym przypadku, jeśli ponownie zdefiniujesz odwołanie args, nie wpłynie to na rzeczywistą wartość przekazaną do funkcji - ponieważ przekazano tylko referencję.
źródło
Mówię ogólnie o oznaczaniu zmiennych i pól jako ostateczne - nie dotyczy to tylko argumentów metod. (Oznaczanie metod / klas końcowych to zupełnie inna sprawa).
To przysługa dla czytelników / przyszłych opiekunów Twojego kodu. Wraz z rozsądną nazwą zmiennej pomaga czytelnikowi twojego kodu zobaczyć / zrozumieć, co reprezentują dane zmienne - i zapewnia czytelnika, że ilekroć zobaczysz zmienną w tym samym zakresie, znaczenie pozostaje. to samo, więc nie musi drapać się po głowie, aby zawsze dowiedzieć się, co oznacza zmienna w każdym kontekście. Widzieliśmy zbyt wiele nadużyć „ponownego wykorzystania” zmiennych, przez co nawet krótki fragment kodu jest trudny do zrozumienia.
źródło
Ostatnie słowo kluczowe zapobiega przypisaniu nowej wartości do parametru. Chciałbym to wyjaśnić na prostym przykładzie
Załóżmy, że mamy metodę
W powyższym przypadku, jeśli "dateOfBirth" zostanie przypisana nowa wartość w method2, to spowoduje to błędne wyjście z method3. Ponieważ wartość, która jest przekazywana do method3, nie jest tym, czym była przed przekazaniem do method2. Aby uniknąć tego ostatniego słowa kluczowego jest używane dla parametrów.
Jest to również jedna z najlepszych praktyk w zakresie kodowania w języku Java.
źródło