Von Nova Trent, Junior Entwicklerin bei Java Fleet Systems Consulting

Schwierigkeit: 🟢 Einsteiger
Lesezeit: 30–35 Minuten
Voraussetzungen: Tag 1–7 abgeschlossen


📋 Kursübersicht: Java OOP in 10 Tagen

TagThemaStatus
1OOP-Konzepte & erste Klasse✅ Abgeschlossen
2Attribute & Methoden✅ Abgeschlossen
3Datenkapselung & Sichtbarkeit✅ Abgeschlossen
4Konstruktoren✅ Abgeschlossen
5Konstanten & Static✅ Abgeschlossen 🔴
6Vererbung – Grundlagen✅ Abgeschlossen
7Vererbung – Polymorphie & Abstrakte Klassen✅ Abgeschlossen
→ 8Typumwandlung & instanceof📍 Du bist hier
9Interfaces & Enumerationen
10Ausnahmebehandlung🔴 KOPFNUSS

Voraussetzung: Tag 1–7 abgeschlossen


🔄 Kurz-Wiederholung: Challenge von Tag 7

Die Aufgabe war: Erstelle eine Mitarbeiter-Hierarchie mit Entwickler und Manager.

Lösung:

// Elternklasse
public abstract class Mitarbeiter {
    protected String name;
    protected String personalnummer;
    protected double gehalt;
    
    public Mitarbeiter(String name, String personalnummer, double gehalt) {
        this.name = name;
        this.personalnummer = personalnummer;
        this.gehalt = gehalt;
    }
    
    public void arbeiten() {
        System.out.println(name + " arbeitet.");
    }
    
    public double getJahresgehalt() {
        return gehalt * 12;
    }
    
    public abstract String getRolle();  // Muss implementiert werden
}

// Kindklasse 1
public class Entwickler extends Mitarbeiter {
    private String programmiersprache;
    
    public Entwickler(String name, String pnr, double gehalt, String sprache) {
        super(name, pnr, gehalt);
        this.programmiersprache = sprache;
    }
    
    @Override
    public void arbeiten() {
        System.out.println(name + " programmiert in " + programmiersprache + ".");
    }
    
    @Override
    public String getRolle() { return "Entwickler"; }
    
    public void coden() {
        System.out.println("Tipptipptipp...");
    }
}

// Kindklasse 2
public class Manager extends Mitarbeiter {
    private int teamgroesse;
    
    public Manager(String name, String pnr, double gehalt, int teamgroesse) {
        super(name, pnr, gehalt);
        this.teamgroesse = teamgroesse;
    }
    
    @Override
    public double getJahresgehalt() {
        return super.getJahresgehalt() * 1.10;  // +10% Bonus
    }
    
    @Override
    public String getRolle() { return "Manager"; }
    
    public void meeting() {
        System.out.println("Meeting um 9 Uhr!");
    }
}

Hast du’s? Super! Heute lernst du, wie du sicher zwischen Typen wechselst.


⚡ Das Wichtigste in 30 Sekunden

Dein Problem: Du hast eine Fahrzeug-Variable, weißt aber, dass ein Auto drin steckt. Wie kommst du an die hupen()-Methode?

Die Lösung: Typumwandlung (Casting)! Aber Vorsicht: Erst mit instanceof prüfen, dann casten.

Heute lernst du:

  • ✅ Upcast — automatisch, immer sicher
  • ✅ Downcast — explizit, kann fehlschlagen
  • instanceof — Typ prüfen vor dem Cast
  • ✅ Pattern Matching (Java 16+) — Prüfen und Casten in einem

Zeit-Investment: 30–35 Minuten


👋 Nova: „Das hat mich vor ClassCastExceptions gerettet!“

Hey! 👋

Nova hier.

Real talk: Ich hab am Anfang ständig ClassCastException bekommen. Elyndra fragte nur: „Hast du mit instanceof geprüft?“ — „Äh… nein?“

Heute zeig ich dir, wie du Typumwandlung sicher machst. Kein Raten mehr, ob ein Cast funktioniert!

Los geht’s! 🚀


🟢 GRUNDLAGEN

Das Problem: Zugriff auf Kind-Methoden

Du hast eine Variable vom Eltern-Typ, aber ein Kind-Objekt drin:

Fahrzeug fahrzeug = new Auto("VW", 2024, 4);

fahrzeug.fahren();  // ✅ OK — Fahrzeug hat fahren()
fahrzeug.hupen();   // ❌ FEHLER! Fahrzeug kennt hupen() nicht!

Der Compiler sieht nur den Variablentyp (Fahrzeug), nicht das tatsächliche Objekt (Auto).

Die Lösung: Downcast

Fahrzeug fahrzeug = new Auto("VW", 2024, 4);

Auto auto = (Auto) fahrzeug;  // Expliziter Cast!
auto.hupen();  // ✅ Jetzt geht's!

Upcast vs. Downcast

Abbildung 1: Upcast ist automatisch und sicher. Downcast ist explizit und kann fehlschlagen.

Upcast (Kind → Eltern):

Auto auto = new Auto("VW", 2024);
Fahrzeug f = auto;  // ✅ Automatisch, kein Cast nötig
  • Immer sicher (jedes Auto IST ein Fahrzeug)
  • Verliert Zugriff auf Kind-Methoden

Downcast (Eltern → Kind):

Fahrzeug f = new Auto("VW", 2024);
Auto a = (Auto) f;  // ⚠️ Expliziter Cast nötig!
  • Kann fehlschlagen!
  • Braucht Typprüfung

Das Problem mit Downcast

Was passiert hier?

Fahrzeug f = new Motorrad("Harley", 2023);
Auto a = (Auto) f;  // 💥 ClassCastException!

Runtime-Fehler:

Exception in thread "main" java.lang.ClassCastException: 
    Motorrad cannot be cast to Auto

Das Objekt ist ein Motorrad, kein Auto. Der Cast schlägt fehl!

Die Lösung: instanceof

Mit instanceof prüfst du den Typ vor dem Cast:

Fahrzeug f = new Auto("VW", 2024);

if (f instanceof Auto) {
    Auto a = (Auto) f;  // Sicher!
    a.hupen();
}

Abbildung 2: instanceof prüft, ob ein Objekt zu einem Typ gehört — inkl. aller Elternklassen.

instanceof-Regeln

Auto auto = new Auto("VW", 2024);

auto instanceof Auto      // true  (ist ein Auto)
auto instanceof Fahrzeug  // true  (ist auch ein Fahrzeug)
auto instanceof Object    // true  (alles ist Object)
auto instanceof Motorrad  // false (ist KEIN Motorrad)

// null ist NICHTS:
Auto nullAuto = null;
nullAuto instanceof Auto  // false (null ist kein Typ)

Pattern Matching (Java 16+)

Ab Java 16 gibt’s eine elegante Kurzform:

Abbildung 3: Pattern Matching kombiniert Prüfung und Cast in einem Schritt.

Vorher (umständlich):

if (f instanceof Auto) {
    Auto a = (Auto) f;
    a.hupen();
}

Nachher (elegant):

if (f instanceof Auto a) {
    a.hupen();  // a ist bereits gecastet!
}

Die Variable a wird nur erstellt, wenn der instanceof-Test erfolgreich ist.

Typische Anwendung: Polymorphe Collections

List<Fahrzeug> fuhrpark = new ArrayList<>();
fuhrpark.add(new Auto("VW", 2024, 4));
fuhrpark.add(new Motorrad("Harley", 2023));
fuhrpark.add(new Auto("BMW", 2022, 2));

// Alle Fahrzeuge durchgehen
for (Fahrzeug f : fuhrpark) {
    f.fahren();  // Geht immer (alle Fahrzeuge können fahren)
    
    // Nur Autos hupen:
    if (f instanceof Auto auto) {
        auto.hupen();
    }
    
    // Nur Motorräder machen Wheelie:
    if (f instanceof Motorrad moto) {
        moto.wheelie();
    }
}

Wann brauche ich Typumwandlung?

SituationLösung
Kind in Eltern-Variable speichernUpcast (automatisch)
Kind-Methoden auf Eltern-Variable aufrufenDowncast + instanceof
Objekte aus heterogener Collection verarbeiteninstanceof
equals() implementiereninstanceof

🟡 PROFESSIONALS

Schon OOP-Erfahrung aus C#, C++, PHP? Hier sind die Java-Besonderheiten.

Für C#-Umsteiger: is und as

// C#
if (f is Auto auto) {
    auto.Hupen();
}

// Oder mit as (liefert null bei Fehlschlag):
Auto a = f as Auto;
if (a != null) { a.Hupen(); }
// Java (ab 16)
if (f instanceof Auto auto) {
    auto.hupen();
}

// Kein "as" in Java — manuell:
Auto a = (f instanceof Auto) ? (Auto) f : null;

Für C++-Umsteiger: dynamic_cast

// C++
Auto* a = dynamic_cast<Auto*>(f);
if (a != nullptr) {
    a->hupen();
}
// Java
if (f instanceof Auto a) {
    a.hupen();
}

Switch mit Pattern Matching (Java 21+)

// Java 21: Switch mit Patterns!
String beschreibung = switch (fahrzeug) {
    case Auto a -> "Auto mit " + a.getAnzahlTueren() + " Türen";
    case Motorrad m -> "Motorrad mit " + m.getHubraum() + " ccm";
    case LKW l -> "LKW mit " + l.getLadekapazitaet() + " kg";
    default -> "Unbekanntes Fahrzeug";
};

🔵 BONUS

Für Wissbegierige: equals(), getClass(), Visitor-Pattern.

equals() richtig implementieren

@Override
public boolean equals(Object obj) {
    // Gleiche Referenz?
    if (this == obj) return true;
    
    // Null oder falscher Typ?
    if (!(obj instanceof Auto other)) return false;
    
    // Attribute vergleichen
    return this.marke.equals(other.marke) 
        && this.baujahr == other.baujahr;
}

instanceof vs. getClass()

// instanceof: Prüft auch Kindklassen
auto instanceof Fahrzeug  // true

// getClass(): Prüft exakten Typ
auto.getClass() == Fahrzeug.class  // false
auto.getClass() == Auto.class      // true

Wann was?

  • instanceof: Für Polymorphie und Vererbung
  • getClass(): Für exakte Typprüfung (selten nötig)

Vermeidung von instanceof: Visitor-Pattern

Wenn du ständig instanceof brauchst, könnte das Visitor-Pattern helfen:

interface FahrzeugVisitor {
    void visit(Auto auto);
    void visit(Motorrad motorrad);
}

abstract class Fahrzeug {
    abstract void accept(FahrzeugVisitor visitor);
}

class Auto extends Fahrzeug {
    @Override
    void accept(FahrzeugVisitor visitor) {
        visitor.visit(this);
    }
}

💬 Real Talk

Tom fragt, Nova erklärt — Die Fragen, die sich jeder stellt.

Java Fleet Kaffeeküche, 14:30 Uhr.


Tom: Nova, warum brauch ich überhaupt Upcast? Das macht doch Java automatisch?

Nova: Stimmt, Upcast ist automatisch. Aber manchmal willst du explizit zeigen, dass du ein Kind als Eltern behandelst. Zum Beispiel bei polymorphen Listen.

Tom: Und Downcast? Wann brauch ich den?

Nova: Wenn du weißt, dass ein spezifischer Typ drin steckt, und du auf dessen Methoden zugreifen willst. Klassiker: Du holst ein Objekt aus einer Collection und brauchst die Kind-Methoden.

Tom: Aber warum nicht einfach gleich den richtigen Typ verwenden?

Nova: lacht Gute Frage! Manchmal kennst du den Typ zur Compile-Zeit nicht. Eine List<Fahrzeug> kann Autos UND Motorräder enthalten. Erst zur Laufzeit weißt du, was drin ist.

Tom: Und Pattern Matching? Ist das nur syntaktischer Zucker?

Nova: Ja und nein. Es ist kürzer, aber auch sicherer. Die Variable existiert nur im Scope, wo sie gültig ist. Weniger Fehlerquellen!


✅ Checkpoint: Hast du es verstanden?

Quiz

Frage 1: Was ist der Unterschied zwischen Upcast und Downcast?

Frage 2: Was liefert null instanceof String?

Frage 3: Wann wirft ein Downcast eine Exception?

Frage 4: Was macht if (f instanceof Auto a)?

Frage 5: Dieser Code:

Object obj = "Hallo";
Integer i = (Integer) obj;

Kompiliert das? Was passiert zur Laufzeit?


Mini-Challenge

Aufgabe: Erstelle ein Tierheim-System:

  1. Abstrakte Klasse Tier:
    • Attribute: name, alter
    • Abstrakte Methode: lautGeben()
    • Methode: info() — gibt Name und Alter aus
  2. Kindklasse Hund:
    • Zusätzliches Attribut: rasse
    • lautGeben() → „Wuff!“
    • Eigene Methode: apportieren()
  3. Kindklasse Katze:
    • Zusätzliches Attribut: istFreigaenger
    • lautGeben() → „Miau!“
    • Eigene Methode: klettern()
  4. Main-Methode:
    • Erstelle eine List<Tier> mit Hunden und Katzen
    • Iteriere und rufe lautGeben() auf
    • Nur Hunde sollen apportieren(), nur Katzen klettern()

Lösung: Findest du am Anfang von Tag 9! 🚀


❓ FAQ — Häufig gestellte Fragen

Frage 1: Kann ich ohne instanceof casten?

Ja, aber riskant! Wenn der Typ nicht passt → ClassCastException. Außer bei Upcast — der ist immer sicher.


Frage 2: Was ist schneller: instanceof oder getClass()?

getClass() ist minimal schneller, aber der Unterschied ist vernachlässigbar. Nimm, was semantisch passt.


Frage 3: Funktioniert instanceof mit Interfaces?

Ja! auto instanceof Fahrbar prüft, ob Auto das Interface implementiert.


Frage 4: Warum ist null instanceof X immer false?

null ist kein Objekt, also kann es zu keinem Typ gehören. Das ist sicherer als eine Exception.


Frage 5: Pattern Matching in älteren Java-Versionen?

Geht nicht. Du brauchst mindestens Java 16 für Pattern Matching mit instanceof.


Frage 6: Kann ich mehrere instanceof in einer Zeile kombinieren?

Ja, mit logischen Operatoren:

if (obj instanceof String s && s.length() > 5) { ... }

Frage 7: Bernd meinte, viel instanceof sei ein „Code Smell“. Stimmt das?

seufzt Typisch Bernd. Er hat einen Punkt: Übermäßiges instanceof kann auf fehlendes Polymorphie-Design hindeuten. Wenn du ständig Typen prüfst, überleg ob du nicht Methoden in die Elternklasse verschieben kannst.

Aber manchmal ist instanceof genau richtig — z.B. bei equals() oder beim Verarbeiten heterogener Collections. Wie immer: Balance. 🤷


📚 Quiz-Lösungen

Frage 1: Unterschied Upcast vs. Downcast?

Antwort:

  • Upcast (Kind → Eltern): Automatisch, immer sicher. Verliert Zugriff auf Kind-Methoden.
  • Downcast (Eltern → Kind): Explizit mit (Typ), kann fehlschlagen. Braucht instanceof-Prüfung.

Frage 2: Was liefert null instanceof String?

Antwort:

false. null gehört zu keinem Typ.


Frage 3: Wann wirft Downcast eine Exception?

Antwort:

Wenn das Objekt zur Laufzeit nicht vom gecasteten Typ ist.

Fahrzeug f = new Motorrad(...);
Auto a = (Auto) f;  // 💥 ClassCastException!

Frage 4: Was macht if (f instanceof Auto a)?

Antwort:

Pattern Matching (Java 16+). Es prüft, ob f ein Auto ist, und erstellt gleichzeitig die Variable a vom Typ Auto. Kein separater Cast nötig!


Frage 5: Kompiliert das? Was passiert?

Object obj = "Hallo";
Integer i = (Integer) obj;

Antwort:

Ja, es kompiliert! Der Compiler sieht nur Object und Integer — das könnte passen.

Zur Laufzeit: ClassCastException! Der String „Hallo“ kann nicht zu Integer gecastet werden.


🎉 Tag 8 geschafft!

Du hast es drauf! 🚀

Das hast du heute gelernt:

  • ✅ Upcast ist automatisch und sicher
  • ✅ Downcast braucht expliziten Cast und Prüfung
  • instanceof prüft den Typ vor dem Cast
  • ✅ Pattern Matching (Java 16+) vereint Prüfung und Cast

🔮 Wie geht’s weiter?

Morgen in Tag 9: Interfaces & Enumerationen

Das wird praktisch! Du lernst:

  • interface — Verträge für Klassen
  • Mehrfachimplementierung (was mit Vererbung nicht geht!)
  • enum — Typsichere Konstanten-Sets
  • Default-Methoden in Interfaces

Interfaces sind überall in Java! 🎯


📦 Downloads

Starter-Projekt für Tag 8:

⬇️ Tag08_Typumwandlung.zip — Komplettes Maven-Projekt

Inhalt:

Tag08_Typumwandlung/
├── pom.xml
├── README.md
└── src/main/java/
    └── de/javafleet/oop/
        ├── Main.java
        └── model/
            ├── Fahrzeug.java
            ├── Auto.java
            ├── Motorrad.java
            ├── Mitarbeiter.java     (Lösung Tag 7)
            ├── Entwickler.java
            └── Manager.java

Grafiken:


🔧 Troubleshooting

Problem: ClassCastException

java.lang.ClassCastException: Motorrad cannot be cast to Auto

Lösung: Immer mit instanceof prüfen vor dem Cast!


Problem: „inconvertible types“

error: inconvertible types: String cannot be converted to Integer

Lösung: Du versuchst, unverwandte Typen zu casten. Das geht nicht!


Problem: Pattern Matching funktioniert nicht

error: pattern matching in instanceof is not supported in -source 11

Lösung: Upgrade auf Java 16+ oder nutze den klassischen Ansatz.


🔗 Resources & Links

🟢 Für Einsteiger

RessourceBeschreibungSprache
Oracle — Type CastingOffizielle Doku🇬🇧
Baeldung — instanceofPraktische Beispiele🇬🇧

🟡 Für Fortgeschrittene

RessourceBeschreibungSprache
JEP 394 — Pattern MatchingFeature-Spezifikation🇬🇧

👋 Bis morgen!

Tag 8 ist durch. Du kannst jetzt sicher zwischen Typen wechseln!

Morgen: Interfaces & Enumerationen — das macht Java erst richtig flexibel.

See you! 🚀


Nova Trent
Junior Entwicklerin bei Java Fleet Systems Consulting
„Erst instanceof, dann cast — so vermeidest du Exceptions!“ 🎯


Tags: #Java #OOP #Typumwandlung #Casting #instanceof #PatternMatching #Tutorial

© 2025 Java Fleet Systems Consulting | java-developer.online

Autor

  • Ensign Nova Trent

    24 Jahre alt, frisch von der Universität als Junior Entwicklerin bei Java Fleet Systems Consulting. Nova ist brilliant in Algorithmen und Datenstrukturen, aber neu in der praktischen Java-Enterprise-Entwicklung. Sie brennt darauf, ihre ersten echten Projekte zu bauen und entdeckt dabei die Lücke zwischen Uni-Theorie und Entwickler-Realität. Sie liebt Star Treck das ist der Grund warum alle Sie Ensign Nova nennen und arbeitet daraufhin das sie Ihren ersten Knopf am Kragen bekommt.