Grundlagen

Motivation für geschachtelte Klassen

Warum braucht man geschachtelte Klassen?

  • Wohin mit Klassen, die nur eine interne Bedeutung haben?
  • Wie übergibt man einfach einen Codeblock an eine Methode?
  • Wie schreibe ich Event-Handler für eine grafische Benutzeroberfläche (GUI)?
  • Wie stellt man eine Klasse zur Verfügung, die Parameter oder Rückgabewerte einer anderen Klasse repräsentiert?

Klassen sind in Java ein mächtiges Mittel zur Strukturierung von Programmen. Klassen können entweder für jeden sichtbar sein (public) oder nur innerhalb des Paketes benutzt werden (default). Was bisher vollkommen fehlt, ist die Möglichkeit Klassen zu definieren, die nur innerhalb einer anderen Klasse benutzt werden können. Diese Lücke wird von den geschachtelten Klassen geschlossen.

Eine der wichtigsten Anwendungszwecke der geschachtelten Klassen liegt bei der Programmierung von grafischen Oberflächen. Hier muss man sehr häufig eine Aktion mit einem Oberflächenelement (z. B. einem Knopf) verknüpfen. Diese Aktion liegt in Form einer Methode vor. Da man aber in Java keine Methoden übergeben kann, muss eine extra Klasse erzeugt werden, um die Methode über den Umweg eines Objektes übergeben zu können. Geschachtelte Klassen bieten hier eine erhebliche Erleichterung, da sie viel weniger Aufwand bei der Programmierung machen.

Mit Java 8 hat eine weitere Vereinfachung Einzug gehalten: durch sog. Lambda-Ausdrücke kann man Methoden noch einfacher als eigenständige Elemente handhaben und an andere Methoden übergeben. Lambdas werden hier aber erst nach den geschachtelten Klassen behandelt, weil sie viele Gemeinsamkeiten haben und historisch gesehen später eingeführt wurden.

Geschachtelte Klassen: Taxonomie

Die Taxonomie zeigt, dass es neben den bisher bekannten Klassen (Toplevel Classes) eine ganze Reihe von anderen Klassen gibt. Hierbei sind allerdings nested und inner classes keine real existierenden Klassen, sondern nur Gruppierungen von weiteren Arten von geschachtelten Klassen.

Geschachtelte Klasse

  • Klassen in Klassen werden als geschachtelte Klassen (nested classes) bezeichnet
  • Schachtelung hat nichts mit Vererbung zu tun
  • Geschachtelte Klasse darf nicht so heißen wie umgebende Klasse

Immer wenn sich eine Klasse in einer anderen Klasse befindet, spricht man von geschachtelten Klassen (nested classes). Wichtig ist, dass die Beziehung zwischen umgebender und geschachtelter Klasse nichts mit Vererbung zu tun hat.

Die geschachtelten Klassen werden danach unterschieden, an welcher Stelle sie sich befinden:

  • innerhalb einer Klasse befinden sich die Static Member Classes und die Nonstatic Member Classes und
  • innerhalb einer Methode findet man die Local Classes und die Anonymous Classes.

Obwohl es einige Unterschiede zwischen den unterschiedlichen geschachtelten Klassen gibt, existieren auch viele Gemeinsamkeiten, die im Folgenden dargestellt werden sollen.

Eine wichtige Regel, die sich aus der internen Implementierung von geschachtelten Klassen ergibt, ist, dass sie nicht so heißen dürfen wie die umgebende Klasse.

Gemeinsamkeiten

Klassen können beliebig tief ineinander geschachtelt werden

class A {
    class B {
        class C {
            class D {
            }
        }
    }
}

Es gibt keine Grenze für die Schachtelungstiefe von Klassen in Klassen. Allerdings hört man in der Praxis, aus Gründen der Übersichtlichkeit, normalerweise bei zwei Ebenen auf, d. h. in eine Toplevel Klasse wird normalerweise nur eine weitere Klasse geschachtelt.

Toplevel Klasse kann beliebige viele geschachtelte Klassen enthalten

class A {
    class B { }
    class C { }
    class D { }
}

Die Anzahl der Klassen, die in einer anderen Klasse enthalten sein können, ist nicht begrenzt.

Geschachtelte Klassen können auch abstrakte Klassen, Interfaces, Enumerationen oder Records sein

class A {
    abstract class B { }
    interface C { }
    class D { }
    enum E { K1, K2; }
}

Obwohl wir von geschachtelten Klassen sprechen, können Interfaces und Enumerationen in eine andere Klasse geschachtelt werden. Die geschachtelte Klasse kann abstrakt sein. Insofern können alle in Java denkbaren Typen in Klassen eingebettet werden.

Geschachtelte Klassen können voneinander oder anderen Klassen erben

class A {
    class B { }
    class C extends B { }
    class D<T> extends ArrayList<T> { }
    class E implements Serializable { }
}

Da es sich bei geschachtelten Klassen um weitgehend normale Klassen handelt, können sie Vererbungsbeziehungen untereinander oder zu anderen Klassen eingehen.

Eine geschachtelte Klasse kann eine beliebige Sichtbarkeit haben

class A {
    private class B { }
    class C { }
    protected class D { }
    public class E { }
}

Geschachtelte Klassen sind genauso Member der umgebenden Klasse wie Attribute und Methoden. Daher können sie mit beliebiger Sichtbarkeit (public, protected, default, private) versehen werden. Hiervon ausgenommen sind nur die lokalen und anonymen Klassen, die gar keinen Sichtbarkeit tragen dürfen, da sie sich innerhalb von Methoden befinden und damit einen lokalen Scope haben (siehe unten).

Geschachtelte Klassen können auf private Eigenschaften der umgebenden Klasse zugreifen

class A {

    private int i = 12;

    class B {
        private int k = i;
    }
}

Eine Besonderheit von geschachtelten Klassen ist deren Fähigkeit, auf alle Eigenschaften der umgebenden Klasse zugreifen zu können, unabhängig von deren Sichtbarkeit. Deshalb können geschachtelte Klasse auf die privaten Attribute und Methoden der umgebenden Klasse zugreifen. Wenn man die bekannte Regel zur Hand nimmt, dass private Eigenschaften im gesamten Rumpf der Klasse sichtbar sind und sich überlegt, dass die geschachtelte Klasse sich ja genau in diesem Rumpf befindet, verliert dieser Zugriff seine Besonderheit.

Die umgebende Klasse kann auf private Eigenschaften der geschachtelten Klasse zugreifen

class C {

    C() {
        D d = new D();
        d.i = 100;
    }

    class D {
        private int i = 10;
    }
}

Analog zum Zugriff der geschachtelten Klasse auf die Attribute der umgebenden Klasse kann diese umgekehrt auf alle Eigenschaften und Methoden der geschachtelten Klasse zugreifen.


Copyright © 2025 Thomas Smits