Verschachtelte Klassen in Java

Geschachtelte Klassen in Java

1. Einführung

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

Einfach ausgedrückt, Java ermöglicht es uns, Klassen innerhalb anderer Klassen zu definieren. Nested classes enable us to logically group classes that are only used in one place, write more readable and maintainable code and increase encapsulation.

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 einige Punkte, die Sie bei statisch verschachtelten Klassen beachten sollten:

  • Wie bei statischen Mitgliedern gehören diese zu ihrer einschließ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 Member in der einschließ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 zu nicht statischen verschachtelten Klassen:

  • 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 Modifikatorstatic deklarieren, handelt es sich um ein statisches Element. Ansonsten ist es eine innere Klasse. Obwohl der Unterschied syntaktisch nur ein einzelnes Schlüsselwort ist (d. H.static), 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 festlegen, 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 eine spezielle Art von inneren Klassen - in denenthe class is defined inside a method oder der Bereichsblock.

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 Member im umschließenden Kontext

  • Sie können nur Instanzmitglieder definieren

Hier 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 eine abstrakte Klasse zu definieren, ohne eine wiederverwendbare Implementierung erstellen zu müssen.

Lassen Sie uns einige Punkte auflisten, die Sie bei anonymen Klassen beachten sollten:

  • Sie können keine Zugriffsmodifikatoren in ihrer Deklaration haben

  • Sie haben Zugriff auf statische und nicht statische Member im umschließenden Kontext

  • Sie können nur Instanzmitglieder definieren

  • Sie sind der einzige Typ verschachtelter 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 AnonymousInnerTest {

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

Weitere Informationen finden Sie in unserem Tutorial zuAnonymous Classes in Java.

4. Beschattung

The declaration of the members of an inner class shadow those of the enclosing class, wenn sie denselben Namen haben.

In diesem Fall bezieht sich das Schlüsselwortthisauf 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

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

  • Deklarieren Sie die verschachtelte Klasse alsstatic

  • Lassen Sie sowohl die verschachtelte Klasse als auch die einschließende KlasseSerializable 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 Feldsichtbarkeit und die Zugriffsmodifikatoren bei den verschiedenen Typen unterscheiden.

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