EMZETT.
Login

Inner Classes

Kurz: Eine Klasse, die innerhalb einer anderen Klasse definiert ist — nützlich, wenn sie inhaltlich eng an die umschließende Klasse gebunden ist und sonst nirgendwo gebraucht wird.

Genauer: Eine nicht-statische innere Klasse hat automatisch Zugriff auf die Felder der äußeren Instanz. Für Klassen, die keinen solchen Zugriff brauchen, ist eine statische verschachtelte Klasse (static class) meist die sauberere Wahl, da sie unabhängig von einer äußeren Instanz existieren kann.

Im Detail

class Auto {
    private String modell = "Model X";
 
    class Motor { // nicht-statische innere Klasse
        void starten() {
            // direkter Zugriff auf das private Feld der äußeren Instanz
            System.out.println(modell + ": Motor startet");
        }
    }
 
    static class Reifen { // statische verschachtelte Klasse
        void aufpumpen() {
            System.out.println("Reifen wird aufgepumpt"); // KEIN Zugriff auf modell möglich
        }
    }
}
 
Auto auto = new Auto();
Auto.Motor motor = auto.new Motor(); // benötigt eine äußere Instanz
motor.starten();
 
Auto.Reifen reifen = new Auto.Reifen(); // braucht KEINE Auto-Instanz
reifen.aufpumpen();

Der entscheidende Unterschied: eine nicht-statische innere Klasse hält intern eine unsichtbare Referenz auf ihre umschließende Instanz und kann daher nicht ohne diese existieren (auto.new Motor()) — dafür hat sie vollen Zugriff auf deren private Felder, auch ohne Getter. Eine static-verschachtelte Klasse verhält sich dagegen praktisch wie eine ganz normale eigenständige Klasse, die nur zur Organisation innerhalb der äußeren Klasse “gruppiert” ist, ohne Zugriff auf deren Instanzfelder. Faustregel: braucht die verschachtelte Klasse Zugriff auf den Zustand der äußeren Instanz → nicht-statisch; ist sie eigenständig und dient nur der logischen Gruppierung (z. B. ein Hilfstyp, der nur innerhalb dieser einen Klasse Sinn ergibt) → static.

Lokale Klassen

Neben inneren und statisch-verschachtelten Klassen gibt es noch lokale Klassen — definiert direkt INNERHALB einer Methode, nur innerhalb dieser Methode sichtbar:

class Berechnung {
    int verarbeite(List<Integer> zahlen) {
        class Zwischenschritt { // nur innerhalb dieser Methode existent
            int quadriere(int x) { return x * x; }
        }
        Zwischenschritt z = new Zwischenschritt();
        return zahlen.stream().mapToInt(z::quadriere).sum();
    }
}

Lokale Klassen sind vergleichsweise selten in modernem Java-Code, da sich die meisten ihrer Anwendungsfälle heute eleganter mit Lambda-Ausdrücken oder Anonymous Classes lösen lassen — sie bleiben aber nützlich, wenn eine Hilfsklasse mehrere Methoden oder einen eigenen Zustand braucht, was ein Lambda nicht abbilden kann.

Praktisches Beispiel: Iterator als innere Klasse

Ein sehr verbreiteter Anwendungsfall für nicht-statische innere Klassen ist die Implementierung eines eigenen Iterators für eine eigene Datenstruktur — der Iterator braucht direkten Zugriff auf die internen Daten der äußeren Klasse:

class EigeneListe {
    private int[] elemente;
 
    class MeinIterator {
        private int position = 0;
        boolean hatNaechstes() { return position < elemente.length; }
        int naechstes() { return elemente[position++]; } // Zugriff auf elemente der äußeren Instanz
    }
}

Siehe auch: Classes, Anonymous Classes