Sobes.tech
Junior

In welchen Fällen kann der Modifikator final in Java angewendet werden?

sobes.tech KI

Antwort von AI

Der Modifikator final in Java kann angewendet werden auf:

  1. Variablen:

    • Lokale Variablen: Ihr Wert wird einmal zugewiesen und kann nach der Initialisierung nicht mehr geändert werden.
    • Klassenfelder: Der Wert des Feldes wird bei der Deklaration oder im Konstruktor zugewiesen und kann danach nicht mehr geändert werden.
    • Methodenparameter: Der Parameter innerhalb der Methode wird zu einer Konstante; er kann innerhalb des Methodenkörpers nicht neu zugewiesen werden.

    Die Anwendung von final auf Variablen gewährleistet:

    • Unveränderlichkeit: Garantie, dass sich der Wert nicht ändert.
    • Thread-Sicherheit: final-Felder einer Klasse sind nach Abschluss des Konstruktors für alle Threads sichtbar, ohne zusätzliche Synchronisation.
    • Compiler-Optimierungen: Der Compiler kann einige Optimierungen vornehmen, da er weiß, dass sich der Wert nicht ändert.
  2. Methoden:

    • Eine als final deklarierte Methode kann in Unterklassen nicht überschrieben werden.
    • Dies ist nützlich für:
      • Verhinderung unerwünschter Verhaltensänderungen: Es wird garantiert, dass die Logik der Methode unverändert bleibt.
      • Förderung der Komposition: Es wird die Verwendung von Komposition anstelle von Vererbung gefördert.
      • Mögliche Compiler-Optimierungen: Der Compiler kann Inline-Expansionen von final-Methoden durchführen.
  3. Klassen:

    • Eine als final deklarierte Klasse kann keine Unterklassen haben.
    • Die Verwendung von final bei Klassen dient dazu:
      • Erstellung unveränderlicher (immutable) Klassen: Zum Beispiel Wrapper-Klassen für Primitive (Integer, String).
      • Schutz des Designs: Verhindert Erweiterungen, die die Invarianten der Klasse verletzen könnten.
      • Erhöhung der Sicherheit: Es wird garantiert, dass das Verhalten der Klasse nicht durch Unterklassen geändert werden kann.
Anwendung Beschreibung Vorteile
final Feld Der Wert wird einmal zugewiesen (bei Deklaration oder im Konstruktor). Unveränderlichkeit, Thread-Sicherheit, Optimierungen.
final Parameter Der Wert kann innerhalb der Methode nicht geändert werden. Klare Signatur, Garantie der Unveränderlichkeit des Parameters.
final Methode Kann in Unterklassen nicht überschrieben werden. Verhinderung von Verhaltensänderungen, Förderung der Komposition, Optimierungen.
final Klasse Kann keine Unterklassen haben (Vererbung ist nicht möglich). Unveränderliche Klasse, Schutz des Designs, erhöhte Sicherheit.

Beispiele:

public class Example {
    // final Klassenfeld
    private final String name;

    // final primitives Feld
    private final int id;

    // final, aber kann Referenz auf verschiedene Objekte vom Typ List haben, solange die Liste nicht erstellt wurde
    // nach der Erstellung kann die Referenz geändert werden, aber nicht die Referenz selbst
    private final List<String> items;

    // Konstante zur Kompilierungszeit
    public static final double PI = 3.14159;

    public Example(String name, int id) {
        this.name = name; // Zuweisung an das final Feld
        this.id = id;     // Zuweisung an das final Feld
        this.items = new ArrayList<>(); // Initialisierung des final Feldes
    }

    // final Methode
    public final void printDetails() {
        System.out.println("Name: " + name + ", ID: " + id);
    }

    // Methode mit final Parameter
    public void addItem(final String item) {
        // item = "neues Element"; // Kompilierungsfehler: Zuweisung an final Variable nicht möglich
        items.add(item);
    }
}

// final Klasse
// public final class ImmutableClass {
//     private final int value;
//
//     public ImmutableClass(int value) {
//         this.value = value;
//     }
//
//     public int getValue() {
//         return value;
//     }
// }

// public class SubclassOfImmutable extends ImmutableClass { // Kompilierungsfehler: Kann nicht von finaler Klasse erben
// }