programowanieProgramista Java

Jak działa mechanizm final w Javie - dla zmiennych, metod i klas, i jakie nieoczekiwane efekty może wywołać niewłaściwe użycie tego modyfikatora?

Zdaj rozmowy kwalifikacyjne z asystentem AI Hintsage

Odpowiedź.

final w Javie jest używane do:

  • Zmiennych — staje się niezmienna po zainicjowaniu;
  • Metod — nie można nadpisać w klasach dziedziczących;
  • Klas — nie można tworzyć klas dziedziczących.

Cechy i subtelności:

  • final zmienna musi być zainicjowana przy deklaracji lub w konstruktorze;
  • final referencja nie pozwala na zmianę referencji, ale obiekt pod referencją można zmieniać (jeśli nie jest immutable!);
  • Dziedziczenie z final klasy (np. String, Math) jest niemożliwe;
  • Nie można nadpisać final metody, nawet jeśli klasa jest dziedziczona.
final class A {} // nie można zrobić class B extends A class Parent { final void foo() { } } class Child extends Parent { // void foo() {} // błąd: nie można nadpisać foo } final int COUNT = 10;

Pytanie z podstępem.

Czy można zmienić stan obiektu, na który wskazuje final zmienna?

Odpowiedź: Tak, jeśli to nie jest obiekt immutable. Na przykład:

final List<String> names = new ArrayList<>(); names.add("Wania"); // To jest dozwolone - zmienia się obiekt pod referencją, ale nie sama referencja names = new ArrayList<>(); // Błąd kompilacji

Przykłady rzeczywistych błędów ze względu na brak znajomości subtelności tematu.


Historia

W systemie logowania jedyny final Logger przekazywany był w całym kodzie, uważając obiekt za całkowicie chroniony – ale zmieniali ustawienia przez publiczną metodę, niszcząc globalnie konfigurację.

Historia

W klasie narzędziowej utworzono final pola typu List, a następnie próbowano je zwracać na zewnątrz do wspólnego użytku. Zewnętrzny kod swobodnie modyfikował zawartość listy przez otrzymaną referencję — final w żaden sposób nie chroni przed tym.

Historia

Pojawiło się zadanie rozszerzenia zewnętrznego API, opartego na final klasach. Z powodu nich rozszerzenie okazało się niemożliwe, trzeba było duplikować logikę i utrzymywać dwie niezależne gałęzie produktu, co skomplikowało migracje.