Advanced Java Services | Einführung |
Mit der Version 1.1 wurde in Java das Konzept der inneren Klassen eingeführt. Ab der Version 1.4
spricht man von geschachtelten Klassen, also nested classes und meint mit inneren Klassen in der Regel
die nichtstatischen und nicht lokalen geschachtelten Klassen.
Während Puristen die Einführung noch heute als nicht (mehr) objektorientiert geißeln, sind nested classes
inzwischen längst nicht mehr aus Java zu vertreiben. Sparsam eingesetzt können sie sehr hilfreich sein
und die Codierung sogar übersichtlicher machen. Der unreflektierte Einsatz von anonymen Klassen etwa
kann aber auch zum genauen Gegenteil führen, nämlich zu schwer durchschaubaren und schwer zu pflegendem
Code.
Ein innere oder geschachtelte Klasse ist eine Klasse in einer Klasse. Sie ist entweder selbst ein Member
einer Klasse oder sie ist deklariert in einer Methode (oder einem Block) oder sie dient als namenlose bzw.
anonyme Klasse sofort zur Instantiierung eines Objektes.
Am besten vergleicht man eine nested class mit einer Variablen (oder Referenz), denn sie hat im
wesentlichen den gleichen Status wie eine Variable. Eine Variable kann Member einer Klasses sein oder
eine Variable kann lokal sein. Dementsprechend kann eine nested class Member einer Klasse sein oder auch
eine lokale Klasse sein. Membervariablen sind statisch oder nichtstatisch und haben zudem einen von vier
Schutzzuständen haben (public, protected, default, private). Dementsprechend sind "Memberklassen"
statisch oder nichtstatisch und haben einen von vier Schutzzuständen.
Lokale Variablen dagegen werden in Methoden oder Blöcken angelegt und gelten nur innerhalb der
entsprechenden Methode oder dem entsprechenden Block. Sind es Referenzen, so werden sie auf dem Heap
angelegt. Sie können als Returnwert zurückgegeben werden. Sie haben keinen Schutzzustand.
Genauso verhält es sich mit lokalen Klassen. Lokale Klassen werden in einer Methode oder in einem
Block deklariert. Anschließend kann man Objekte dieser Klassen anlegen. Ihr Geltungsbereich ist die
Methode oder der Block, in dem sie stehen. Da es Referenzen sind, werden sie auf dem Heap angelegt.
Sie können über return zurückgegeben werden. Sie haben keinen Schutzzustand.
Anonyme Klassen dagegen dienen unmittelbar zum Anlegen von Objekten und sind daher immer mit einer
Art von Konstruktoraufruf verbunden.
Nun gibt es zudem auch noch nested interfaces und innere Klassen in interfaces. Nehmen wir zuerst
nested interfaces, also interfaces innerhalb von Klassen. Diese existieren (gottseidank...) nur
auf Memberebene und sind immer automatisch statisch. Lokale oder gar anonyme Interfaces
(wie sollte man ein solches implementieren...) gibt es glücklicherweise nicht.
Umgekehrt gibt es allerdings nested classes innerhalb von Interfaces. Diese unterliegen ähnlichen
Einschränkungen wie die anderen Members eines Interfaces. Sie sind automatisch public (wie die Methoden)
und automatisch static (wie die Datenmembers), aber nicht automatisch final.
Alles klar?
Wem das noch nicht reicht, kann sich überlegen, wie und was man noch alles mehrfach schachteln kann...
Eine Klasse, die keine umschließende Klasse besitzt, ist eine top-level-Klasse. Eine top-level-Klasse ist unabhängig von einem Objekt oder von einer Methode. Eine nested class ist nur dann eine top-level-Klasse, wenn sie statisch ist. Demnach ist eine nested class in einem Interface eine top-level-Klasse. Umgekehrt sind interfaces immer top-level, egal ob geschachtelt oder nicht.