CodeGym /Kurse /JAVA 25 SELF /Pattern Matching for instanceof

Pattern Matching for instanceof

JAVA 25 SELF
Level 65 , Lektion 1
Verfügbar

1. Das Problem des klassischen instanceof

Beginnen wir mit etwas Nostalgie. Vor Java 16 musste man, wenn man den Typ eines Objekts prüfen und es anschließend als diesen Typ verwenden wollte, ein wortreiches Muster mit instanceof-Prüfung und explizitem Cast schreiben:

Object obj = ...; // irgendein Objekt

if (obj instanceof String) {
    String s = (String) obj;
    System.out.println("Länge des Strings: " + s.length());
}

Langweilig, aber häufiges Muster

Dieses Pattern begegnet sehr oft – Event-Handler, Arbeit mit heterogenen Collections, Business-Logik mit Vererbung usw.

Warum das unpraktisch ist

  • Code-Duplizierung – man muss den Typ zweimal angeben: sowohl in instanceof als auch im Cast.
  • Fehlerrisiko – man kann leicht versehentlich in den falschen Typ casten und eine ClassCastException erhalten.
  • „Noisy“-Code – die Lesbarkeit leidet, besonders bei mehreren Prüfungen.

2. Pattern Matching for instanceof: Neue Syntax

In Java 16 wurde Pattern Matching für instanceof hinzugefügt. Jetzt prüft man den Typ und deklariert sofort eine Variable des gewünschten Typs, die innerhalb des if-Zweigs verfügbar ist.

Neue Syntax

if (obj instanceof String s) {
    // s ist bereits ein String!
    System.out.println("Stringlänge: " + s.length());
}
  • Nach dem Typ in instanceof schreibt man den Namen der neuen Variablen: String s.
  • Die Variable ist nur innerhalb des Blocks sichtbar, in dem die Bedingung wahr ist.
  • Kein Cast (String) notwendig – der Compiler stellt das sicher.

Wo liegt die Magie? Der Compiler prüft den Typ und, falls er passt, bindet er die Variable des gewünschten Typs. Andernfalls wird der Block einfach nicht ausgeführt.

Wie das im realen Code aussieht

Object obj = "Hallo, Java 16+!";

if (obj instanceof String s) {
    System.out.println("Großbuchstaben: " + s.toUpperCase());
} else {
    System.out.println("Das ist kein String!");
}

3. Sicherheit und Lesbarkeit: warum das großartig ist

Die Fehlerart ClassCastException wird ausgeschlossen

Object obj = 123;
// String s = (String) obj; // Boom! Ausnahme.

Mit Pattern Matching wird die Variable nur bei erfolgreicher Typprüfung erzeugt – ein „falscher“ Cast existiert schlicht nicht.

Der Code wird kürzer und verständlicher
Zwei Zeilen werden zu einer. Weniger „Noisy“-Code – leichter zu lesen und zu warten.

Beispiel: unterschiedliche Typen verarbeiten

public static void printInfo(Object obj) {
    if (obj instanceof String s) {
        System.out.println("String mit Länge " + s.length());
    } else if (obj instanceof Integer i) {
        System.out.println("Ganzzahl: " + (i + 1));
    } else {
        System.out.println("Unbekannter Typ: " + obj);
    }
}

4. Anwendungsbeispiele und Feinheiten

Prüfung mehrerer Typen

Object value = ...;

if (value instanceof String s) {
    System.out.println("Das ist ein String: " + s);
} else if (value instanceof Number n) {
    System.out.println("Das ist eine Zahl: " + n);
} else {
    System.out.println("Etwas anderes: " + value);
}

Verwendung mit null
Wenn das Objekt null ist, liefert instanceof immer false – es gibt keine NPE, aber der Block wird nicht ausgeführt.

Object obj = null;

if (obj instanceof String s) {
    // Dieser Block wird NIEMALS ausgeführt, wenn obj == null
    System.out.println("String: " + s);
} else {
    System.out.println("obj ist null oder kein String");
}

Pattern Matching mit Vererbung

class Animal {}
class Dog extends Animal {
    void bark() { System.out.println("Wuff!"); }
}

Animal a = new Dog();

if (a instanceof Dog d) {
    d.bark(); // Wir können Dog-Methoden ohne Cast aufrufen!
}

Wichtig ist die Reihenfolge der Prüfungen: von spezifisch zu allgemein, sonst greifen die „engen“ Prüfungen ggf. nicht.

Vergleich: alter und neuer Ansatz

Alter Ansatz Neuer Ansatz (Pattern Matching)
if (obj instanceof Cat) {
    Cat c = (Cat) obj;
    c.meow();
}
if (obj instanceof Cat c) {
    c.meow();
}

5. Einschränkungen von Pattern Matching für instanceof

  • Gültigkeitsbereich der Variablen. Die im Pattern eingeführte Variable ist nur in dem Zweig sichtbar, in dem die Prüfung wahr ist.
if (obj instanceof String s) {
    System.out.println(s); // s ist verfügbar
}
// System.out.println(s); // Fehler! s ist hier nicht sichtbar
  • Es ist nicht möglich, mehrere Variablen unterschiedlicher Typen in einer Bedingung zu deklarieren.
// Compilerfehler:
if (obj instanceof String s || obj instanceof Integer i) {
    // ...
}
  • Erfordert Java 16+. In älteren JDK-Versionen wird die neue Syntax nicht unterstützt.

6. Praxisbeispiele (auf Basis einer einfachen Anwendung)

Stellen wir uns einen einfachen Task-Manager mit verschiedenen Aufgabentypen vor.

Klassen

class Task {
    String title;
    public Task(String title) { this.title = title; }
}

class BugTask extends Task {
    int severity;
    public BugTask(String title, int severity) {
        super(title);
        this.severity = severity;
    }
}

class FeatureTask extends Task {
    String feature;
    public FeatureTask(String title, String feature) {
        super(title);
        this.feature = feature;
    }
}

Verarbeitung mit Pattern Matching

public static void processTask(Task t) {
    if (t instanceof BugTask bug) {
        System.out.println("Bug: " + bug.title + ", Schweregrad: " + bug.severity);
    } else if (t instanceof FeatureTask feature) {
        System.out.println("Feature: " + feature.title + ", Modul: " + feature.feature);
    } else if (t instanceof Task task) {
        System.out.println("Normale Aufgabe: " + task.title);
    }
}

7. Nützliche Feinheiten

Tabelle: Pattern Matching für instanceof – Vor- und Nachteile

Vorteile Nachteile/Einschränkungen
Weniger Code, bessere Lesbarkeit Erfordert Java 16+
Kein Risiko für ClassCastException Variable ist nur innerhalb des if-Blocks sichtbar
Typsicherheit auf Compiler-Ebene Funktioniert nicht für mehrere Typen in einer Bedingung
Praktisch für die Verarbeitung von Vererbung Kann in alten IDEs und Builds nicht unterstützt werden
Geeignet für beliebige Klassen

Visualisierung: wie Pattern Matching für instanceof funktioniert

+---------------------------+
|      Object obj           |
+---------------------------+
            |
            v
  if (obj instanceof Type t)
            |
      Ja           Nein
   (true)        (false)
    |               |
    v               v
 t ist verfügbar  t existiert nicht
   (Code)           (kein Zugriff)

8. Typische Fehler bei der Verwendung von Pattern Matching for instanceof

Fehler Nr. 1: Versuch, die Variable außerhalb des if-Blocks zu verwenden. Die Variable wurde im Pattern deklariert; verlässt man den Block, existiert sie nicht mehr. Der Compiler beschwert sich zu Recht: „Was ist s?“

Fehler Nr. 2: Erwartung, dass instanceof für null funktioniert. Ist das Objekt null, ist die Bedingung instanceof immer falsch, die Variable wird nicht erzeugt. Behandeln Sie null bei Bedarf separat.

Fehler Nr. 3: Verwendung der neuen Syntax auf einer alten JDK/IDE-Version. Unter Java 11 und darunter ist Pattern Matching für instanceof nicht verfügbar – es führt zu einem Syntaxfehler. Prüfen Sie die JDK-Version.

Fehler Nr. 4: Verwechslung des Gültigkeitsbereichs. Die im Pattern eingeführte Variable ist nur in dem Zweig verfügbar, in dem die Prüfung wahr ist. Außerhalb existiert sie nicht.

Fehler Nr. 5: Erwartung gleichzeitiger Unterstützung mehrerer Typen. Man kann nicht zwei Variablen verschiedener Typen in einer Bedingung deklarieren: if (obj instanceof String s || obj instanceof Integer i) – so geht es nicht. Für jeden Typ ist eine eigene Prüfung nötig.

Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION