Verschachtelte Klassen in Java

1. Einleitung

Dieses Tutorial ist eine schnelle und genaue Einführung in verschachtelte Klassen in der Java-Sprache.

Mit Java können wir Klassen in anderen Klassen definieren. Verschachtelte Klassen ermöglichen es uns, Klassen, die nur an einer Stelle verwendet werden, logisch zu gruppieren, besser lesbaren und wartbaren Code zu schreiben und die Kapselung zu erhöhen.

Bevor wir beginnen, werfen wir einen Blick auf die verschiedenen Arten verschachtelter Klassen, die in der Sprache verfügbar sind:

  • Statisch verschachtelte Klassen
  • Nicht statische verschachtelte Klassen
  • Lokale Klassen
  • Anonyme Klassen

In den nächsten Abschnitten werden wir diese im Detail besprechen.

2. Statisch verschachtelte Klassen

Hier sind einige Punkte, die Sie bei statisch verschachtelten Klassen beachten sollten:

  • Wie bei statischen Elementen gehören diese zu ihrer umschließenden Klasse und nicht zu einer Instanz der Klasse
  • Sie können alle Arten von Zugriffsmodifikatoren in ihrer Deklaration haben
  • Sie haben nur Zugriff auf statische Elemente in der umschließenden Klasse
  • Sie können sowohl statische als auch nicht statische Elemente definieren

Mal sehen, wie wir eine statisch verschachtelte Klasse deklarieren können:

public class Enclosing { private static int x = 1; public static class StaticNested { private void run() { // method implementation } } @Test public void test() { Enclosing.StaticNested nested = new Enclosing.StaticNested(); nested.run(); } }

3. Nicht statische verschachtelte Klassen

Im Folgenden finden Sie einige wichtige Punkte, die Sie bei nicht statisch verschachtelten Klassen beachten sollten:

  • Sie werden auch innere Klassen genannt
  • Sie können alle Arten von Zugriffsmodifikatoren in ihrer Deklaration haben
  • Genau wie Instanzvariablen und -methoden werden innere Klassen einer Instanz der einschließenden Klasse zugeordnet
  • Sie haben Zugriff auf alle Mitglieder der einschließenden Klasse, unabhängig davon, ob sie statisch oder nicht statisch sind
  • Sie können nur nicht statische Elemente definieren

So können wir eine innere Klasse deklarieren:

public class Outer { public class Inner { // ... } }

Wenn wir eine verschachtelte Klasse mit einem statischen Modifikator deklarieren , handelt es sich um ein statisches Element. Ansonsten ist es eine innere Klasse. Obwohl der Unterschied syntaktisch nur ein einzelnes Schlüsselwort (dh statisch ) ist, gibt es semantisch einen großen Unterschied zwischen diesen Arten verschachtelter Klassen. Instanzen der inneren Klasse sind an die Instanzen der einschließenden Klasse gebunden und haben daher Zugriff auf ihre Mitglieder. Wir sollten uns dieses Problems bewusst sein, wenn wir auswählen, ob eine verschachtelte Klasse eine innere Klasse sein soll.

Um eine innere Klasse zu instanziieren, müssen wir zuerst ihre einschließende Klasse instanziieren.

Mal sehen, wie wir das machen können:

Outer outer = new Outer(); Outer.Inner inner = outer.new Inner();

In den nächsten Unterabschnitten werden wir einige spezielle Arten innerer Klassen zeigen.

3.1. Lokale Klassen

Lokale Klassen sind ein spezieller Typ innerer Klassen, bei denen die Klasse innerhalb einer Methode oder eines Bereichsblocks definiert wird.

Sehen wir uns einige Punkte an, die Sie bei dieser Art von Klasse beachten sollten:

  • Sie können keine Zugriffsmodifikatoren in ihrer Deklaration haben
  • Sie haben Zugriff auf statische und nicht statische Elemente im umschließenden Kontext
  • Sie können nur Instanzmitglieder definieren

Hier ist ein kurzes Beispiel:

public class NewEnclosing { void run() { class Local { void run() { // method implementation } } Local local = new Local(); local.run(); } @Test public void test() { NewEnclosing newEnclosing = new NewEnclosing(); newEnclosing.run(); } }

3.2. Anonyme Klassen

Anonyme Klassen können verwendet werden, um eine Implementierung einer Schnittstelle oder einer abstrakten Klasse zu definieren, ohne eine wiederverwendbare Implementierung erstellen zu müssen.

Lassen Sie uns einige Punkte auflisten, an die Sie sich bei anonymen Klassen erinnern sollten:

  • Sie können keine Zugriffsmodifikatoren in ihrer Deklaration haben
  • Sie haben Zugriff auf statische und nicht statische Elemente im umschließenden Kontext
  • Sie können nur Instanzmitglieder definieren
  • Sie sind die einzigen verschachtelten Klassen, die keine Konstruktoren definieren oder andere Klassen oder Schnittstellen erweitern / implementieren können

Um eine anonyme Klasse zu definieren, definieren wir zunächst eine einfache abstrakte Klasse:

abstract class SimpleAbstractClass { abstract void run(); }

Nun wollen wir sehen, wie wir eine anonyme Klasse definieren können:

public class AnonymousInnerUnitTest { @Test public void whenRunAnonymousClass_thenCorrect() { SimpleAbstractClass simpleAbstractClass = new SimpleAbstractClass() { void run() { // method implementation } }; simpleAbstractClass.run(); } }

Weitere Informationen finden Sie in unserem Tutorial zu anonymen Klassen in Java.

4. Beschattung

Die Deklaration der Mitglieder einer inneren Klasse beschattet die der einschließenden Klasse, wenn sie denselben Namen haben.

In diesem Fall bezieht sich das Schlüsselwort this auf die Instanzen der verschachtelten Klasse, und auf die Mitglieder der äußeren Klasse kann mit dem Namen der äußeren Klasse verwiesen werden.

Sehen wir uns ein kurzes Beispiel an:

public class NewOuter { int a = 1; static int b = 2; public class InnerClass { int a = 3; static final int b = 4; public void run() { System.out.println("a = " + a); System.out.println("b = " + b); System.out.println("NewOuterTest.this.a = " + NewOuter.this.a); System.out.println("NewOuterTest.b = " + NewOuter.b); System.out.println("NewOuterTest.this.b = " + NewOuter.this.b); } } @Test public void test() { NewOuter outer = new NewOuter(); NewOuter.InnerClass inner = outer.new InnerClass(); inner.run(); } }

5. Serialisierung

Um eine java.io.NotSerializableException beim Versuch, eine verschachtelte Klasse zu serialisieren, zu vermeiden , sollten wir:

  • Deklarieren Sie die verschachtelte Klasse als statisch
  • Lassen Sie sowohl die verschachtelte Klasse als auch die einschließende Klasse Serializable implementieren

6. Fazit

In diesem Artikel haben wir gesehen, was verschachtelte Klassen sind und welche unterschiedlichen Typen sie haben. Wir haben uns auch angesehen, wie sich die Feldsichtbarkeits- und Zugriffsmodifikatoren zwischen diesen verschiedenen Typen unterscheiden.

Wie immer finden Sie die vollständige Implementierung dieses Tutorials auf GitHub.