Słowo kluczowe final
Część sekcji Programowanie obiektowe ścieżki Java w Coddy. Lekcja 13 z 87.
Słowo kluczowe final w Javie uniemożliwia modyfikację. Można je stosować do zmiennych, metod i klas, a w każdym przypadku ma inny efekt.
Gdy zastosujesz zmienną, final sprawi, że stanie się stałą — po przypisaniu jej wartości nie można zmienić:
public class Circle {
private final double PI = 3.14159;
private final double radius;
public Circle(double radius) {
this.radius = radius; // Można przypisać wartość raz w konstruktorze
}
public void setRadius(double r) {
// this.radius = r; // Błąd! Nie można ponownie przypisać wartości zmiennej final
}
}Zmienna final musi zostać zainicjalizowana podczas deklaracji lub w konstruktorze. Później każda próba przypisania jej nowej wartości powoduje błąd kompilacji.
W przypadku typów referencyjnych final oznacza, że referencja nie może wskazywać na inny obiekt, ale zawartość obiektu nadal może się zmieniać:
private final StringBuilder name = new StringBuilder("John");
// name = new StringBuilder("Jane"); // Błąd! Nie można ponownie przypisać
name.append(" Doe"); // OK! Zawartość obiektu może się zmieniaćUżycie final z polami jasno komunikuje zamiar — informuje innych programistów, że ta wartość nie powinna się zmieniać po inicjalizacji. Jest to szczególnie przydatne w przypadku wartości konfiguracyjnych, identyfikatorów lub wszelkich danych, które muszą pozostać stałe przez cały czas życia obiektu.
final metody nie można nadpisać w podklasie:
class Base {
public final void greet() {
System.out.println("Hi");
}
}
class Child extends Base {
// public void greet() { } // Błąd! greet() jest final w Base
}Klasy final w ogóle nie można rozszerzyć. String jest klasą finalną, więc żadna klasa nie może jej rozszerzyć:
final class Config { }
// class MyConfig extends Config { } // Błąd! Config jest finalWyzwanie
ŁatwyZbudujmy system rejestracji Student, który używa słowa kluczowego final, aby chronić dane, które nie powinny się zmieniać po zarejestrowaniu studenta.
Utworzysz dwa pliki, aby uporządkować swój kod:
Student.java: Utwórz klasę Student, w której niektóre informacje zostaną trwale zablokowane po ich ustawieniu:- Pole
finalstudentId(String) — przypisywane podczas tworzenia i niezmienne - Pole
finalenrollmentYear(int) — rok, w którym student rozpoczął naukę; również niezmienny - Zwykłe prywatne pole
name(String) — można je zaktualizować, jeśli student zmieni imię - Konstruktor, który przyjmuje wszystkie trzy wartości i inicjalizuje pola
- Getter
getStudentId()zwracający identyfikator studenta - Getter
getEnrollmentYear()zwracający rok rozpoczęcia nauki - Getter
getName()i settersetName()dla imienia - Metodę
getInfo(), która zwraca:"ID: [studentId] | Name: [name] | Enrolled: [enrollmentYear]"
- Pole
Main.java: Utwórz obiekt Student, a następnie zaktualizuj jego imię i wyświetl jego informacje. Otrzymasz cztery dane wejściowe: identyfikator studenta, początkowe imię, rok rozpoczęcia nauki i nowe imię. Wypisz dwa wiersze:- Informacje o studencie przed zmianą imienia
- Informacje o studencie po zmianie imienia
Otrzymasz kolejno cztery dane wejściowe: studentId (String), name (String), enrollmentYear (int) i newName (String).
Zwróć uwagę, jak pola final chronią identyfikator studenta i rok rozpoczęcia nauki — są to stałe dane, które nie powinny się zmieniać, podczas gdy imię można zaktualizować za pomocą settera.
Spróbuj swoich sił
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Odczytaj dane wejściowe
String studentId = scanner.nextLine();
String name = scanner.nextLine();
int enrollmentYear = scanner.nextInt();
scanner.nextLine(); // odczytaj znak nowej linii
String newName = scanner.nextLine();
// TODO: Utwórz obiekt Student z wartościami początkowymi
// TODO: Wyświetl informacje o studencie przed zmianą imienia
// TODO: Zaktualizuj imię studenta za pomocą settera
// TODO: Wyświetl informacje o studencie po zmianie imienia
}
}
Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Programowanie obiektowe
1Podstawy programowania obiektowego
Pliki zewnętrzneWprowadzenie do programowania obiektowegoKlasy a obiektySłowo kluczowe thisMetodyPola (atrybuty)Metoda konstruktoraPrzeciążanie konstruktoraPodsumowanie — prosty kalkulator4Dziedziczenie
Podstawy dziedziczenia (extends)Słowo kluczowe superPrzesłanianie metod (@Override)Łańcuch wywołań konstruktorówKlasa ObjectDziedziczenie jedno- i wielopoziomoweDlaczego Java nie obsługuje wielodziedziczenia klasPodsumowanie – hierarchia pracowników7Metody specjalne i klasa Object
Metoda toString()equals() i hashCode()Metoda clone()compareTo() i ComparableInterfejs ComparatorPodsumowanie — własne sortowanie10Obsługa wyjątków w programowaniu obiektowym
Hierarchia klas wyjątkówWłasne wyjątkiBłędy sprawdzane a niesprawdzaneWzorzec try-with-resourcesPodsumowanie – zweryfikowany użytkownik2Modyfikatory dostępu i enkapsulacja
Przegląd poziomów dostępuMetody pobierające i ustawiająceUkrywanie informacjiSłowo kluczowe finalPodsumowanie — menedżer kont bankowych5Polimorfizm
Podstawy przeciążania metodPrzesłanianie metod (w czasie wykonywania)Rzutowanie w górę i w dółOperator instanceofKlasy i metody abstrakcyjnePowtórka — kalkulator figur8Zaawansowane koncepcje OOP
Kompozycja a dziedziczenieAgregacja a kompozycjaKlasy wewnętrzne, zagnieżdżone i anonimoweEnumy i metody enumówRekordy (Java 16+)Klasy zapieczętowane (Java 17+)11Wzorce projektowe — część 1
Wprowadzenie do wzorców projektowychWzorzec SingletonWzorzec FactoryWzorzec BuilderWzorzec ObserverWzorzec Strategy3Właściwości klas i składowe statyczne
Zmienne instancji a zmienne statyczneMetody statyczneBloki statyczneStałe (static final)Powtórka – Counter i Utility6Interfejsy i klasy abstrakcyjne
Wprowadzenie do interfejsówImplementowanie interfejsówImplementacja wielu interfejsówMetody domyślne i statyczne w interfejsieKlasy abstrakcyjne a interfejsyInterfejsy funkcyjnePodsumowanie — system płatnościPoćwicz samodzielnie: Kompilator Java online