it-swarm-eu.dev

Java innere Klasse und statische verschachtelte Klasse

Was ist der Hauptunterschied zwischen einer inneren Klasse und einer statischen verschachtelten Klasse in Java? Spielt Design/Implementierung eine Rolle bei der Auswahl einer davon?

1585
Omnipotent

Aus dem Java Tutorial :

Geschachtelte Klassen werden in zwei Kategorien unterteilt: statisch und nicht statisch. Verschachtelte Klassen, die als statisch deklariert sind, werden einfach als statische verschachtelte Klassen bezeichnet. Nicht statische verschachtelte Klassen werden als innere Klassen bezeichnet. 

Auf statische verschachtelte Klassen wird mit dem umgebenden Klassennamen zugegriffen:

OuterClass.StaticNestedClass

Um beispielsweise ein Objekt für die statische verschachtelte Klasse zu erstellen, verwenden Sie diese Syntax:

OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();

Objekte, die Instanzen einer inneren Klasse sind, sind in einer Instanz der äußeren Klasse vorhanden. Betrachten Sie die folgenden Klassen:

class OuterClass {
    ...
    class InnerClass {
        ...
    }
}

Eine InnerClass-Instanz kann nur in einer OuterClass-Instanz vorhanden sein und hat direkten Zugriff auf die Methoden und Felder ihrer umschließenden Instanz.

Um eine innere Klasse zu instanziieren, müssen Sie zuerst die äußere Klasse instanziieren. Dann erstellen Sie das innere Objekt innerhalb des äußeren Objekts mit dieser Syntax:

OuterClass.InnerClass innerObject = outerObject.new InnerClass();

siehe: Java-Tutorial - Geschachtelte Klassen

Der Vollständigkeit halber sei darauf hingewiesen, dass es auch eine innere Klasse ohne eine einschließende Instanz gibt :

class A {
  int t() { return 1; }
  static A a =  new A() { int t() { return 2; } };
}

Hier ist new A() { ... } eine innere Klasse, die in einem statischen Kontext definiert ist, und hat keine einschließende Instanz.

1564
Martin

Das Java-Tutorial sagt :

Terminologie: Geschachtelte Klassen sind in zwei Kategorien unterteilt: statisch und nicht statisch. Verschachtelte Klassen, die werden als statisch deklariert. statische verschachtelte Klassen. Nicht statisch Geschachtelte Klassen heißen inner Klassen.

Im allgemeinen Sprachgebrauch werden die Begriffe "verschachtelt" und "inner" von den meisten Programmierern austauschbar verwendet, aber ich verwende den korrekten Begriff "verschachtelte Klasse", der sowohl innere als auch statische umfasst.

Klassen können ad infinitum verschachtelt sein, z. Klasse A kann Klasse B enthalten, die Klasse C enthält, die Klasse D usw. enthält. Mehr als eine Ebene der Klassenverschachtelung ist jedoch selten, da es sich im Allgemeinen um ein schlechtes Design handelt.

Es gibt drei Gründe, warum Sie eine verschachtelte Klasse erstellen können:

  • organisation: Manchmal ist es am sinnvollsten, eine Klasse in den Namespace einer anderen Klasse zu sortieren, insbesondere wenn sie in keinem anderen Kontext verwendet wird
  • zugriff: Geschachtelte Klassen haben besonderen Zugriff auf die Variablen/Felder ihrer Klassen (genau, welche Variablen/Felder von der Art der verschachtelten Klasse abhängen, ob innere oder statische Klasse).
  • bequemlichkeit: Das Erstellen einer neuen Datei für jeden neuen Typ ist ebenfalls lästig, insbesondere wenn der Typ nur in einem Kontext verwendet wird

Es gibt vier verschachtelte Klassen in Java. Kurz gesagt, sie sind:

  • static class: wird als statisches Mitglied einer anderen Klasse deklariert
  • innere Klasse: Wird als Instanzmitglied einer anderen Klasse deklariert
  • local inner class: Wird innerhalb einer Instanzmethode einer anderen Klasse deklariert
  • anonyme innere Klasse: wie eine lokale innere Klasse, jedoch als Ausdruck geschrieben, der ein einmaliges Objekt zurückgibt

Lassen Sie mich noch näher darauf eingehen.


Statische Klassen

Statische Klassen sind am einfachsten zu verstehen, da sie nichts mit Instanzen der enthaltenden Klasse zu tun haben.

Eine statische Klasse ist eine Klasse, die als statisches Mitglied einer anderen Klasse deklariert ist. Genau wie andere statische Member ist eine solche Klasse nur ein Hanger, der die enthaltende Klasse als Namespace verwendet, zB die Klasse Goat, die als statisches Member der Klasse Rhino im Paket Pizza ist unter dem Namen pizza.Rhino.Goat bekannt.

package pizza;

public class Rhino {

    ...

    public static class Goat {
        ...
    }
}

Ehrlich gesagt sind statische Klassen ein ziemlich wertloses Feature, da Klassen bereits nach Paketen in Namespaces unterteilt sind. Der einzig mögliche Grund, eine statische Klasse zu erstellen, besteht darin, dass eine solche Klasse Zugriff auf die privaten statischen Member der enthaltenen Klasse hat. Ich halte dies jedoch für eine recht lahmere Begründung für das Vorhandensein der statischen Klasse.


Innere Klassen

Eine innere Klasse ist eine Klasse, die als nicht statisches Mitglied einer anderen Klasse deklariert ist:

package pizza;

public class Rhino {

    public class Goat {
        ...
    }

    private void jerry() {
        Goat g = new Goat();
    }
}

Wie bei einer statischen Klasse wird die innere Klasse durch ihren enthaltenden Klassennamen pizza.Rhino.Goat als qualifiziert bezeichnet, aber innerhalb der enthaltenden Klasse kann sie unter ihrem einfachen Namen bekannt sein. Jede Instanz einer inneren Klasse ist jedoch an eine bestimmte Instanz ihrer enthaltenden Klasse gebunden: Oben ist der in jerry erstellte Goat implizit an den Rhinogebunden. _ Instanz das in Jerry. Andernfalls machen wir die zugehörige Rhino-Instanz explizit, wenn wir Goat instanziieren:

Rhino rhino = new Rhino();
Rhino.Goat goat = rhino.new Goat();

(Beachten Sie, dass Sie sich auf den inneren Typ als Goat in der seltsamen neu - Syntax beziehen: Java schließt den übergeordneten Typ aus dem Rhino -Part. (new rhino.Goat ())} _ hätte auch für mich mehr Sinn ergeben.)

Was bringt uns das? Nun, die innere Klasseninstanz hat Zugriff auf die Instanzmitglieder der enthaltenden Klasseninstanz. Auf diese einschließenden Instanzmitglieder wird innerhalb der inneren Klasse via nur auf ihre einfachen Namen Bezug genommen, nicht auf viathis (this in der inneren Klasse bezieht sich auf die innere Klasseninstanz, nicht auf die zugehörige enthaltende Klasseninstanz): 

public class Rhino {

    private String barry;

    public class Goat {
        public void colin() {
            System.out.println(barry);
        }
    }
}

In der inneren Klasse können Sie auf this der enthaltenden Klasse als Rhino.this verweisen, und Sie können this verwenden, um sich auf ihre Mitglieder zu beziehen, zB Rhino.this.barry.


Lokale innere Klassen

Eine lokale innere Klasse ist eine Klasse, die im Hauptteil einer Methode deklariert ist. Eine solche Klasse ist nur innerhalb der enthaltenen Methode bekannt, sodass sie nur instanziiert werden kann und deren Member innerhalb der enthaltenen Methode aufgerufen werden können. Der Vorteil ist, dass eine lokale Instanz der inneren Klasse an die endgültigen lokalen Variablen der enthaltenen Methode gebunden ist. Wenn die Instanz ein finales Local der enthaltenen Methode verwendet, behält die Variable ihren Wert zum Zeitpunkt der Erstellung der Instanz bei, selbst wenn die Variable den Gültigkeitsbereich der Instanz überschritten hat (tatsächlich handelt es sich hierbei um die grobe, begrenzte Version von Closures von Java).Da eine lokale innere Klasse weder Mitglied einer Klasse noch eines Pakets ist, wird sie nicht mit einer Zugriffsebene deklariert. (Beachten Sie jedoch, dass die eigenen Mitglieder wie in einer normalen Klasse über Zugriffsebenen verfügen.).

Wenn eine lokale innere Klasse in einer Instanzmethode deklariert wird, ist eine Instantiierung der inneren Klasse an die Instanz gebunden, die zum Zeitpunkt der Erstellung der Instanz this der enthaltenden Methode gehalten wird, und somit die Instanzmitglieder der enthaltenden Klasse sind wie in einer Instanz innere Klasse zugänglich. Eine lokale innere Klasse wird instanziiert: via ihr Name, z. B. lokale innere Klasse Cat wird als neue Cat () instanziiert, nicht neu this.Cat () wie Sie vielleicht erwarten.

.


Eine anonyme innere Klasse ist eine syntaktisch bequeme Art, eine lokale innere Klasse zu schreiben. In der Regel wird eine lokale innere Klasse bei jeder Ausführung der enthaltenen Methode höchstens einmal instanziiert. Es wäre also schön, wenn wir die lokale innere Klassendefinition und ihre einzelne Instanziierung in einer bequemen Syntaxform kombinieren könnten, und es wäre auch schön, wenn wir uns keinen Namen für die Klasse ausdenken müssten (je weniger hilfreich) Namen, die Ihr Code enthält, desto besser). Eine anonyme innere Klasse lässt beides zu:

new *ParentClassName*(*constructorArgs*) {*members*}

new *InterfaceName*() {*members*}

Auch wenn Sie einer anonymen inneren Klasse keinen Konstruktor zuweisen können, können Sie mit einem Initialisierungsblock (einem {} -Block, der sich außerhalb einer Methode befindet) ein beliebiges Setup vornehmen.

Machen Sie sich klar, dass eine anonyme innere Klasse einfach weniger flexibel ist, um eine lokale innere Klasse mit einer Instanz zu erstellen. Wenn Sie eine lokale innere Klasse wünschen, die mehrere Schnittstellen implementiert oder Schnittstellen implementiert, während Sie eine andere Klasse als Object erweitern oder die ihren eigenen Konstruktor angibt, bleiben Sie beim Erstellen einer regulären, benannten lokalen inneren Klasse.

Be clear that an anonymous inner class is simply a less flexible way of creating a local inner class with one instance. If you want a local inner class which implements multiple interfaces or which implements interfaces while extending some class other than Object or which specifies its own constructor, you're stuck creating a regular named local inner class.

553
Jegschemesch

Ich glaube nicht, dass der wahre Unterschied in den obigen Antworten deutlich wurde. 

Um die Bedingungen richtig zu machen: 

  • Eine verschachtelte Klasse ist eine Klasse, die auf Quellcodeebene in einer anderen Klasse enthalten ist.
  • Es ist statisch, wenn Sie es mit dem Modifizierer static deklarieren.
  • Eine nicht statische verschachtelte Klasse wird als innere Klasse bezeichnet. (Ich bleibe bei einer nicht statischen verschachtelten Klasse.)

Martins Antwort ist soweit richtig. Die eigentliche Frage lautet jedoch: Was ist der Zweck, eine geschachtelte Klasse als statisch zu deklarieren oder nicht?

Sie verwenden statische verschachtelte Klassen , wenn Sie Ihre Klassen nur zusammenhalten möchten, wenn sie topisch zusammengehören oder die verschachtelte Klasse ausschließlich in der umgebenden Klasse verwendet wird. Es gibt keinen semantischen Unterschied zwischen einer statisch verschachtelten Klasse und jeder anderen Klasse.

Nicht statische verschachtelte Klassen sind ein anderes Tier. Ähnlich wie anonyme innere Klassen sind solche verschachtelten Klassen tatsächlich Schließungen. Das heißt, sie erfassen ihren umgebenden Geltungsbereich und ihre einschließende Instanz und machen diese zugänglich. Vielleicht wird ein Beispiel dies verdeutlichen. Siehe diesen Stub eines Containers:

public class Container {
    public class Item{
        Object data;
        public Container getContainer(){
            return Container.this;
        }
        public Item(Object data) {
            super();
            this.data = data;
        }

    }

    public static Item create(Object data){
        // does not compile since no instance of Container is available
        return new Item(data);
    }
    public Item createSubItem(Object data){
        // compiles, since 'this' Container is available
        return new Item(data);
    }
}

In diesem Fall möchten Sie eine Referenz von einem untergeordneten Element auf den übergeordneten Container haben. Bei Verwendung einer nicht statischen verschachtelten Klasse funktioniert dies ohne Arbeit. Sie können auf die umgebende Instanz von Container mit der Syntax Container.this zugreifen.

Weitere Hardcore-Erklärungen folgen:

Wenn Sie sich die Java-Bytecodes ansehen, die der Compiler für eine (nicht statische) geschachtelte Klasse generiert, kann dies noch deutlicher werden:

// class version 49.0 (49)
// access flags 33
public class Container$Item {

  // compiled from: Container.Java
  // access flags 1
  public INNERCLASS Container$Item Container Item

  // access flags 0
  Object data

  // access flags 4112
  final Container this$0

  // access flags 1
  public getContainer() : Container
   L0
    LINENUMBER 7 L0
    ALOAD 0: this
    GETFIELD Container$Item.this$0 : Container
    ARETURN
   L1
    LOCALVARIABLE this Container$Item L0 L1 0
    MAXSTACK = 1
    MAXLOCALS = 1

  // access flags 1
  public <init>(Container,Object) : void
   L0
    LINENUMBER 12 L0
    ALOAD 0: this
    ALOAD 1
    PUTFIELD Container$Item.this$0 : Container
   L1
    LINENUMBER 10 L1
    ALOAD 0: this
    INVOKESPECIAL Object.<init>() : void
   L2
    LINENUMBER 11 L2
    ALOAD 0: this
    ALOAD 2: data
    PUTFIELD Container$Item.data : Object
    RETURN
   L3
    LOCALVARIABLE this Container$Item L0 L3 0
    LOCALVARIABLE data Object L0 L3 2
    MAXSTACK = 2
    MAXLOCALS = 3
}

Wie Sie sehen, erstellt der Compiler ein verstecktes Feld Container this$0. Dies wird im Konstruktor festgelegt, der über einen zusätzlichen Parameter vom Typ Container verfügt, um die einschließende Instanz anzugeben. Sie können diesen Parameter nicht in der Quelle sehen, der Compiler generiert ihn jedoch implizit für eine verschachtelte Klasse. 

Martins Beispiel

OuterClass.InnerClass innerObject = outerObject.new InnerClass();

würde so zu einem Aufruf von etwas wie (in Bytecodes) kompiliert werden

new InnerClass(outerObject)

Der Vollständigkeit halber:

Eine anonyme Klasse ist ist ein perfektes Beispiel für eine nicht statische verschachtelte Klasse, der gerade kein Name zugeordnet ist und später nicht mehr referenziert werden kann.

131
jrudolph

Ich denke, keine der obigen Antworten erklärt Ihnen den wirklichen Unterschied zwischen einer verschachtelten Klasse und einer statischen verschachtelten Klasse in Bezug auf das Anwendungsdesign: 

Überblick

Eine verschachtelte Klasse kann nicht statisch oder statisch sein und ist in jedem Fall eine innerhalb einer anderen Klasse definierte Klasse . Eine geschachtelte Klasse sollte nur vorhanden sein, um die Klasse einzuschließen , wenn eine verschachtelte Klasse für andere Klassen nützlich ist (nicht nur die einschließenden), sollte sie als oberste Klasse deklariert werden.

Unterschied

Nonstatic Nested class : ist implizit mit der umgebenden Instanz der enthaltenden Klasse verbunden. Dies bedeutet, dass Methoden und Zugriffsvariablen der umgebenden Instanz aufgerufen werden können. Eine nicht statische verschachtelte Klasse wird häufig zum Definieren einer Adapterklasse verwendet.

Statische verschachtelte Klasse : kann nicht auf die umgebende Klasseninstanz zugreifen und Methoden für diese Instanz aufrufen. Sie sollte daher verwendet werden, wenn die verschachtelte Klasse keinen Zugriff auf eine Instanz der umgebenden Klasse erfordert. Eine statische verschachtelte Klasse wird häufig zum Implementieren von Komponenten des äußeren Objekts verwendet.

Fazit

Der Hauptunterschied zwischen den beiden ist vom Design-Standpunkt aus: nicht statisch geschachtelte Klasse kann auf die Instanz der Containerklasse zugreifen, während statisch nicht.

88
aleroot

In einfachen Worten, wir brauchen geschachtelte Klassen vor allem, weil Java keine Schließungen bereitstellt.

Geschachtelte Klassen sind Klassen, die im Körper einer anderen umgebenden Klasse definiert sind. Es gibt zwei Arten - statisch und nicht statisch.

Sie werden als Mitglieder der umgebenden Klasse behandelt. Daher können Sie einen der vier Zugriffsbezeichner angeben: private, package, protected, public. Wir haben diesen Luxus nicht mit Top-Level-Klassen, die nur als public oder package-private deklariert werden können.

Innere Klassen, auch Nicht-Stapel-Klassen, haben Zugriff auf andere Mitglieder der Top-Klasse, auch wenn sie als privat deklariert sind, während statische verschachtelte Klassen keinen Zugriff auf andere Mitglieder der Top-Klasse haben.

public class OuterClass {
    public static class Inner1 {
    }
    public class Inner2 {
    }
}

Inner1 ist unsere statische innere Klasse und Inner2 ist unsere innere Klasse, die nicht statisch ist. Der Hauptunterschied zwischen ihnen ist, dass Sie keine Inner2-Instanz ohne ein Äußeres erstellen können, da Sie ein Inner1-Objekt unabhängig voneinander erstellen können.

Wann würden Sie die innere Klasse verwenden?

Stellen Sie sich eine Situation vor, in der Class A und Class B verwandt sind, Class B auf Class A Mitglieder zugreifen muss und Class B nur auf Class A bezogen ist. Innere Klassen kommen ins Bild.

Um eine Instanz der inneren Klasse zu erstellen, müssen Sie eine Instanz Ihrer äußeren Klasse erstellen.

OuterClass outer = new OuterClass();
OuterClass.Inner2 inner = outer.new Inner2();

oder

OuterClass.Inner2 inner = new OuterClass().new Inner2();

Wann würden Sie die statische innere Klasse verwenden?

Sie würden eine statische innere Klasse definieren, wenn Sie wissen, dass sie keine Beziehung zur Instanz der umgebenden Klasse/Top-Klasse hat. Wenn Ihre innere Klasse keine Methoden oder Felder der äußeren Klasse verwendet, ist dies nur eine Verschwendung von Platz, also machen Sie sie statisch.

Um beispielsweise ein Objekt für die statische verschachtelte Klasse zu erstellen, verwenden Sie diese Syntax:

OuterClass.Inner1 nestedObject = new OuterClass.Inner1();

Der Vorteil einer statischen verschachtelten Klasse besteht darin, dass sie kein Objekt der enthaltenden Klasse/Top-Klasse benötigt, um zu funktionieren. Auf diese Weise können Sie die Anzahl der Objekte reduzieren, die Ihre Anwendung zur Laufzeit erstellt.

31
Thalaivar

Ich denke, die übliche Konvention ist die folgende:

  • statische Klasse innerhalb einer Top-Level-Klasse ist eine verschachtelte Klasse
  • Nicht statische Klasse innerhalb einer Top-Level-Klasse ist eine innere Klasse , wobei zwei weitere Formen hat:
    • lokale Klasse - benannte Klassen, die innerhalb eines Blocks wie eine Methode oder ein Konstruktorkörper deklariert sind
    • anonyme Klasse - unbenannte Klassen, deren Instanzen in Ausdrücken und Anweisungen erstellt werden

Einige andere Punkte zur Erinnerung sind jedoch:

  • Klassen der obersten Ebene und statische verschachtelte Klassen sind semantisch gleich, mit der Ausnahme, dass sie bei statisch verschachtelten Klassen statische Verweise auf private statische Felder/Methoden ihrer Klasse Outer [Parent] und umgekehrt beziehen können.

  • Innere Klassen haben Zugriff auf Instanzvariablen der umgebenden Instanz der Outer [parent] -Klasse. Allerdings haben nicht alle inneren Klassen einschließende Instanzen, z. B. innere Klassen in statischen Kontexten, wie eine anonyme Klasse, die in einem statischen Initialisierungsblock verwendet wird, nicht.

  • Die anonyme Klasse erweitert standardmäßig die übergeordnete Klasse oder implementiert die übergeordnete Schnittstelle. Es gibt keine weitere Klausel, um eine andere Klasse zu erweitern oder weitere Schnittstellen zu implementieren. So,

    • new YourClass(){}; bedeutet class [Anonymous] extends YourClass {}
    • new YourInterface(){}; bedeutet class [Anonymous] implements YourInterface {}

Ich habe das Gefühl, dass die größere Frage offen bleibt, welche Frage wann verwendet wird. Das hängt hauptsächlich davon ab, mit welchem ​​Szenario Sie sich befassen, aber das Lesen der Antwort von @jrudolph kann Ihnen helfen, eine Entscheidung zu treffen.

26
sactiw

Hier sind die wichtigsten Unterschiede und Ähnlichkeiten zwischen der inneren Java-Klasse und der statischen verschachtelten Klasse.

Ich hoffe es hilft!

Innere Klasse

  • Kann auf auf die äußere Klasse sowohl auf Instanzen als auch auf statische Methoden und Felder zugreifen
  • Mit der Instanz der einschließenden Klasse verknüpft, damit zum Instanziieren zuerst eine Instanz der äußeren Klasse benötigt wird (Anmerkung neu Schlüsselwortstelle:

    Outerclass.InnerClass innerObject = outerObject.new Innerclass();
    
  • Kann keine static-Mitglieder selbst definieren

  • Kann keine Class - oder Interface -Deklaration haben

Statisch verschachtelte Klasse

  • Kann nicht auf äußere Klasse instance -Methoden oder -Felder zugreifen

  • Keiner Instanz zugeordnet, die Klasse einschließt.

    OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();
    

Ähnlichkeiten

  • Beide Inner-Klassen können auch auf private Felder und Methoden von outer class zugreifen.
  • Auch die Outer-Klasse hat Zugriff auf private Felder und Methoden von inneren Klassen.
  • Beide Klassen können über einen privaten, geschützten oder öffentlichen Zugriffsmodifikator verfügen

Warum verschachtelte Klassen verwenden?

Laut Oracle-Dokumentation gibt es mehrere Gründe ( vollständige Dokumentation ):

  • Es ist eine Möglichkeit, Klassen, die nur an einer Stelle verwendet werden, logisch zu gruppieren: Wenn eine Klasse nur für eine andere Klasse nützlich ist, ist es logisch, sie in diese Klasse einzubetten und die beiden zusammen zu halten. Durch das Schachteln solcher "Hilfsklassen" wird das Paket rationalisiert.

  • Erhöht die Kapselung: Betrachten Sie zwei Klassen der obersten Ebene, A und B, in denen B Zugriff auf Mitglieder von A benötigt, die sonst als privat deklariert würden. Durch das Ausblenden der Klasse B in der Klasse A können die Mitglieder von A als privat deklariert werden und B kann auf sie zugreifen. Außerdem kann B selbst vor der Außenwelt verborgen werden.

  • Dies kann zu besser lesbarem und wartungsfähigerem Code führen: Durch das Verschachteln kleiner Klassen in Klassen der obersten Ebene wird der Code näher an den Verwendungsort gesetzt.

26

Geschachtelte Klasse: Klasse innerhalb der Klasse

Arten:

  1. Statisch verschachtelte Klasse
  2. Nicht statische verschachtelte Klasse [Innere Klasse]

Unterschied:

Nicht statische verschachtelte Klasse [Innere Klasse]

In einer nicht statischen verschachtelten Klasse befinden sich Objekte der inneren Klasse innerhalb des Objekts der äußeren Klasse. Auf dieses Datenelement der äußeren Klasse kann also auf die innere Klasse zugegriffen werden. Um ein Objekt der inneren Klasse zu erstellen, müssen wir zuerst ein Objekt der äußeren Klasse erstellen.

outerclass outerobject=new outerobject();
outerclass.innerclass innerobjcet=outerobject.new innerclass(); 

Statisch verschachtelte Klasse

In statischen verschachtelten Klassenobjekten der inneren Klasse ist kein Objekt der äußeren Klasse erforderlich, da das Wort "statisch" keine Notwendigkeit zum Erstellen eines Objekts anzeigt.

class outerclass A {
    static class nestedclass B {
        static int x = 10;
    }
}

Wenn Sie auf x zugreifen möchten, schreiben Sie die folgende inside-Methode

  outerclass.nestedclass.x;  i.e. System.out.prinltn( outerclass.nestedclass.x);
15
tejas

Die Verwendung geschachtelter statischer Klassen ist subtil und kann in bestimmten Situationen nützlich sein.

Während statische Attribute instanziiert werden, bevor die Klasse über ihren Konstruktor instanziiert wird, scheinen statische Attribute in geschachtelten statischen Klassen nicht instanziiert zu werden, bis der Konstruktor der Klasse __.l aufgerufen wird oder zumindest nicht nach den Attributen werden zuerst referenziert, auch wenn sie als 'final' markiert sind.

Betrachten Sie dieses Beispiel:

public class C0 {

    static C0 instance = null;

    // Uncomment the following line and a null pointer exception will be
    // generated before anything gets printed.
    //public static final String outerItem = instance.makeString(98.6);

    public C0() {
        instance = this;
    }

    public String makeString(int i) {
        return ((new Integer(i)).toString());
    }

    public String makeString(double d) {
        return ((new Double(d)).toString());
    }

    public static final class nested {
        public static final String innerItem = instance.makeString(42);
    }

    static public void main(String[] argv) {
        System.out.println("start");
        // Comment out this line and a null pointer exception will be
        // generated after "start" prints and before the following
        // try/catch block even gets entered.
        new C0();
        try {
            System.out.println("retrieve item: " + nested.innerItem);
        }
        catch (Exception e) {
            System.out.println("failed to retrieve item: " + e.toString());
        }
        System.out.println("finish");
    }
}

Obwohl 'verschachtelt' und 'innerItem' beide als 'static final' deklariert sind. Die Einstellung .__ von verschachtelten.innerItem-Einstellungen wird erst ausgeführt, nachdem die Klasse instanziiert wurde (oder mindestens erst nachdem das verschachtelte statische Element zum ersten Mal referenziert wurde), wie Sie selbst sehen können und unkommentieren die Zeilen, auf die ich mich oben beziehe. Dasselbe gilt nicht für Für 'outerItem'.

Zumindest sehe ich das in Java 6.0.

11
HippoMan

Die Instanz der inneren Klasse wird erstellt, wenn die Instanz der äußeren Klasse erstellt wird. Daher haben die Member und Methoden der inneren Klasse Zugriff auf die Member und Methoden der Instanz (Objekt) der äußeren Klasse. Wenn die Instanz der äußeren Klasse den Gültigkeitsbereich verlässt, existieren auch die Instanzen der inneren Klasse nicht mehr.

Die statische verschachtelte Klasse hat keine konkrete Instanz. Es wird nur geladen, wenn es zum ersten Mal verwendet wird (genau wie bei den statischen Methoden). Es ist eine völlig unabhängige Entität, deren Methoden und Variablen keinen Zugriff auf die Instanzen der äußeren Klasse haben.

Die statischen verschachtelten Klassen sind nicht mit dem äußeren Objekt gekoppelt, sie sind schneller und benötigen keinen Heap/Stack-Speicher, da keine Instanz einer solchen Klasse erstellt werden muss. Als Faustregel gilt, zu versuchen, statisch verschachtelte Klassen mit einem möglichst begrenzten Umfang (private> = class> = protected> = public) zu definieren und diese dann in eine innere Klasse zu konvertieren (durch Entfernen des "statischen" Bezeichners) und zu lösen der Umfang, wenn es wirklich notwendig ist.

11
rmaruszewski

Ich glaube nicht, dass hier viel hinzugefügt werden muss. Die meisten Antworten erklären die Unterschiede zwischen statisch verschachtelten Klassen und inneren Klassen perfekt. Berücksichtigen Sie jedoch das folgende Problem, wenn Sie verschachtelte Klassen gegenüber inneren Klassen verwenden. Wie in einigen Antworten erwähnt, können innere Klassen nicht ohne Instanz der umgebenden Klasse instanziiert werden, was bedeutet, dass sie HOLD a pointer auf die Instanz ihrer einschließenden Instanz setzen Klasse, die zu einer Speicherüberlauf- oder Stack-Overflow-Ausnahme führen kann, weil der GC die umschließenden Klassen nicht sammeln kann, selbst wenn sie nicht mehr verwendet werden. Um dies klar zu stellen, überprüfen Sie den folgenden Code: 

public class Outer {


    public  class Inner {

    }


    public Inner inner(){
        return new Inner();
    }

    @Override
    protected void finalize() throws Throwable {
    // as you know finalize is called by the garbage collector due to destroying an object instance
        System.out.println("I am destroyed !");
    }
}


public static void main(String arg[]) {

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

    // out instance is no more used and should be garbage collected !!!
    // However this will not happen as inner instance is still alive i.e used, not null !
    // and outer will be kept in memory until inner is destroyed
    outer = null;

    //
    // inner = null;

    //kick out garbage collector
    System.gc();

}

Wenn Sie den Kommentar zu // inner = null; entfernen, wird das Programm ausgegeben "Ich werde zerstört!", Aber das Beibehalten dieses Kommentars wird es nicht tun.
Der Grund ist, dass auf die weiße innere Instanz immer noch verwiesen wird. GC kann sie nicht sammeln, und da sie auf die äußere Instanz verweist (mit einem Zeiger darauf verweist), wird sie auch nicht erfasst. Wenn Sie genug dieser Objekte in Ihrem Projekt haben, kann der Speicher ausgehen.
Verglichen mit statischen inneren Klassen, die keinen Punkt auf die Instanz der inneren Klasse enthalten, da sie nicht auf Instanzen, sondern auf Klassen bezogen ist. Das obige Programm kann "ich werde zerstört!" Drucken, wenn Sie die innere Klasse statisch machen und mit Outer.Inner i = new Outer.Inner(); instanziieren. 

10
Adelin

Bei der Instanzerstellung wird die Instanz der nicht-statischen inneren Klasse mit der Referenz auf das Objekt der äußeren Klasse erstellt, in der sie definiert ist. Diese Bedeutet, dass sie die Instanz . Enthält. Die Instanz der statischen inneren Klasse wird jedoch mit der Referenz der äußeren Klasse erstellt, nicht mit Der Referenz des Objekts der äußeren Klasse. Dies bedeutet, dass Keine Instanz enthält.

Zum Beispiel:

class A
{
  class B
  {
    // static int x; not allowed here…..    
  }
  static class C
  {
    static int x; // allowed here
  }
}

class Test
{
  public static void main(String… str)
  {
    A o=new A();
    A.B obj1 =o.new B();//need of inclosing instance

    A.C obj2 =new A.C();

    // not need of reference of object of outer class….
  }
}
10
Ankit Jain

Die Begriffe werden synonym verwendet. Wenn Sie wirklich pedantisch sein wollen, dann definieren Sie könnte "verschachtelte Klasse", um auf eine statische innere Klasse zu verweisen, die keine einschließende Instanz hat. Im Code könnten Sie so etwas haben:

public class Outer {
    public class Inner {}

    public static class Nested {}
}

Das ist jedoch keine allgemein akzeptierte Definition.

8
Daniel Spiewak

Verschachtelte Klasse ist ein sehr allgemeiner Begriff: Jede Klasse, die nicht die oberste Ebene ist, ist eine verschachtelte Klasse .. Eine innere Klasse ist eine nicht statische verschachtelte Klasse .. Joseph Darcy hat eine sehr nette Erklärung zu Nested, Inner geschrieben , Mitglied und Top-Level-Klassen .

8

Targeting-Lernender, der Neuling in Java und/oder geschachtelten Klassen ist 

Geschachtelte Klassen können Folgendes sein:
1. Statisch verschachtelte Klassen.
2. Nicht statische verschachtelte Klassen. (auch bekannt als Innere Klassen ) => Bitte denken Sie daran


1.Inneren Klassen
Beispiel:

class OuterClass  {
/*  some code here...*/
     class InnerClass  {  }
/*  some code here...*/
}


Innere Klassen sind Teilmengen verschachtelter Klassen:

  • innere Klasse ist ein bestimmter Typ verschachtelter Klassen
  • innere Klassen sind Teilmengen verschachtelter Klassen
  • Sie können sagen, dass eine innere Klasse auch eine verschachtelte Klasse ist, Sie können jedochNICHTsagen, dass eine verschachtelte Klasse auch eine innere Klasse ist. 

Spezialität der inneren Klasse:

  • instanz einer inneren Klasse hat Zugriff auf alle Mitglieder der äußeren Klasse, auch diejenigen, die als "privat" gekennzeichnet sind


2.Statisch verschachtelte Klassen:
Beispiel:

class EnclosingClass {
  static class Nested {
    void someMethod() { System.out.println("hello SO"); }
  }
}

Fall 1: Instanziieren einer statischen verschachtelten Klasse aus einer nicht einschließenden Klasse

class NonEnclosingClass {

  public static void main(String[] args) {
    /*instantiate the Nested class that is a static
      member of the EnclosingClass class:
    */

    EnclosingClass.Nested n = new EnclosingClass.Nested(); 
    n.someMethod();  //prints out "hello"
  }
}

Fall 2: Instanziieren einer statischen verschachtelten Klasse aus einer umgebenden Klasse

class EnclosingClass {

  static class Nested {
    void anotherMethod() { System.out.println("hi again"); } 
  }

  public static void main(String[] args) {
    //access enclosed class:

    Nested n = new Nested(); 
    n.anotherMethod();  //prints out "hi again"
  }

}

Spezialität der statischen Klassen:

  • Eine statische innere Klasse hätte nur Zugriff auf die statischen Member der äußeren Klasse und keinen Zugriff auf nicht statische Member.

Fazit:
Frage: Was ist der Hauptunterschied zwischen einer inneren Klasse und einer statischen verschachtelten Klasse in Java?
Antwort: Gehen Sie nur die Details der oben genannten Klassen durch.

7
VdeX

Ummm ... eine innere Klasse IS eine verschachtelte Klasse ... meinst du anonyme Klasse und innere Klasse?

Edit: Wenn Sie eigentlich inner vs anonym gemeint haben ... ist eine innere Klasse nur eine Klasse, die in einer Klasse definiert ist, wie zum Beispiel:

public class A {
    public class B {
    }
}

Während eine anonyme Klasse eine Erweiterung einer anonym definierten Klasse ist, wird keine tatsächliche Klasse definiert, wie in:

public class A {
}

A anon = new A() { /* you could change behavior of A here */ };

Weitere Bearbeitung:

Wikipedia behauptet, es gibt einen Unterschied in Java, aber ich arbeite seit 8 Jahren mit Java, und es ist das erste Mal, dass ich eine solche Unterscheidung hörte ... ganz zu schweigen davon, dass es dort keine Hinweise gibt, die den Anspruch unterstützen Unterm Strich ist eine innere Klasse eine innerhalb einer Klasse definierte Klasse (statisch oder nicht), und geschachtelt ist nur ein weiterer Begriff, der dasselbe bedeutet.

Es gibt einen geringfügigen Unterschied zwischen statischen und nicht statischen verschachtelten Klassen ... Grundsätzlich haben nicht statische innere Klassen impliziten Zugriff auf Instanzfelder und Methoden der umgebenden Klasse (daher können sie nicht in einem statischen Kontext erstellt werden, es wird ein Compiler sein Error). Statische verschachtelte Klassen hingegen haben keinen impliziten Zugriff auf Instanzfelder und -methoden und können in einem statischen Kontext erstellt werden.

7
Mike Stone

Innere Klasse und verschachtelte statische Klasse in Java sind beide Klassen, die in einer anderen Klasse deklariert sind und in Java als Top-Level-Klasse bezeichnet werden. Wenn Sie in der Java-Terminologie eine verschachtelte Klasse als statisch deklarieren, wird sie in Java als verschachtelte statische Klasse bezeichnet, während die nicht statische verschachtelte Klasse einfach als Innere Klasse bezeichnet wird. 

Was ist innere Klasse in Java?

Jede Klasse, die keine oberste Ebene ist oder in einer anderen Klasse deklariert ist, wird als verschachtelte Klasse bezeichnet. Aus diesen verschachtelten Klassen werden Klassen, die nicht statisch sind, in Java als innere Klasse bezeichnet. Es gibt drei Arten der inneren Klasse in Java:

1) Lokale innere Klasse - wird innerhalb eines Codeblocks oder einer Methode deklariert.
2) Anonyme innere Klasse - ist eine Klasse, deren Name nicht referenziert und an derselben Stelle initialisiert werden soll, an der sie erstellt wird.
3) Innere Klasse des Mitglieds - wird als nicht statisches Mitglied der äußeren Klasse deklariert.

public class InnerClassTest {
    public static void main(String args[]) {      
        //creating local inner class inside method i.e. main() 
        class Local {
            public void name() {
                System.out.println("Example of Local class in Java");

            }
        }      
        //creating instance of local inner class
        Local local = new Local();
        local.name(); //calling method from local inner class

        //Creating anonymous inner class in Java for implementing thread
        Thread anonymous = new Thread(){
            @Override
            public void run(){
                System.out.println("Anonymous class example in Java");
            }
        };
        anonymous.start();

        //example of creating instance of inner class
        InnerClassTest test = new InnerClassTest();
        InnerClassTest.Inner inner = test.new Inner();
        inner.name(); //calling method of inner class
    }

     //Creating Inner class in Java
    private class Inner{
        public void name(){
            System.out.println("Inner class example in Java");
        }
    }
}

Was ist eine geschachtelte statische Klasse in Java?

Verschachtelte statische Klasse ist eine andere Klasse, die innerhalb einer Klasse als Member deklariert und als statisch definiert wird. Geschachtelte statische Klasse wird auch als Mitglied der äußeren Klasse deklariert und kann wie jedes andere Mitglied als privat, öffentlich oder geschützt beschrieben werden. Einer der Hauptvorteile der geschachtelten statischen Klasse gegenüber der inneren Klasse besteht darin, dass die Instanz der geschachtelten statischen Klasse nicht an eine umgebende Instanz der äußeren Klasse angehängt ist. Sie benötigen auch keine Instanz der Outer-Klasse, um eine Instanz der verschachtelten statischen Klasse in Java zu erstellen..

1) Es kann auf statische Datenmitglieder der äußeren Klasse einschließlich privat zugreifen.
2) Statisch verschachtelte Klasse kann nicht auf nicht statisches (Instanz-) Datenmitglied} oder Methode zugreifen.

public class NestedStaticExample {
    public static void main(String args[]){  
        StaticNested nested = new StaticNested();
        nested.name();
    }  
    //static nested class in Java
    private static class StaticNested{
        public void name(){
            System.out.println("static nested class example in Java");
        }
    }
}

Ref: Innere Klasse und geschachtelte statische Klasse in Java mit Beispiel

6
roottraveller

Wenn wir eine statische Member-Klasse innerhalb einer Klasse deklarieren, wird sie als oberste verschachtelte Klasse oder statische verschachtelte Klasse bezeichnet. Es kann wie folgt gezeigt werden: 

class Test{
    private static int x = 1;
        static class A{
        private static int y = 2;
        public static int getZ(){
            return B.z+x;
        }
    }
    static class B{
        private static int z = 3;
        public static int getY(){
            return A.y;
        }
    }
}

class TestDemo{
     public static void main(String[] args){
        Test t = new Test();
        System.out.println(Test.A.getZ());
        System.out.println(Test.B.getY());
    }
}

Wenn wir eine nicht statische Member-Klasse innerhalb einer Klasse deklarieren, spricht man von inneren Klasse. Die innere Klasse kann wie folgt gezeigt werden: 

    class Test{
        private int i = 10;
        class A{
            private int i =20;
            void display(){
            int i = 30;
            System.out.println(i);
            System.out.println(this.i);
            System.out.println(Test.this.i);
        }
    }
}
5
Pankti

Ich denke, die Leute hier sollten zu Poster bemerken, dass: Static Nest Class nur die erste innere Klasse.

 public static class A {} //ERROR

 public class A {
     public class B {
         public static class C {} //ERROR
     }
 }

 public class A {
     public static class B {} //COMPILE !!!

 }

Zusammenfassend kann gesagt werden, dass die statische Klasse nicht davon abhängt, welche Klasse sie enthält. So können sie nicht im normalen Unterricht sein. (weil normale Klasse eine Instanz benötigt).

5
hqt

Das folgende ist ein Beispiel für static nested class und inner class:

OuterClass.Java

public class OuterClass {
     private String someVariable = "Non Static";

     private static String anotherStaticVariable = "Static";  

     OuterClass(){

     }

     //Nested classes are static
     static class StaticNestedClass{
        private static String privateStaticNestedClassVariable = "Private Static Nested Class Variable"; 

        //can access private variables declared in the outer class
        public static void getPrivateVariableofOuterClass(){
            System.out.println(anotherStaticVariable);
        }
     }

     //non static
     class InnerClass{

         //can access private variables of outer class
         public String getPrivateNonStaticVariableOfOuterClass(){
             return someVariable;
         }
     }

     public static void accessStaticClass(){
         //can access any variable declared inside the Static Nested Class 
         //even if it private
         String var = OuterClass.StaticNestedClass.privateStaticNestedClassVariable; 
         System.out.println(var);
     }

}

OuterClassTest:

public class OuterClassTest {
    public static void main(String[] args) {

        //access the Static Nested Class
        OuterClass.StaticNestedClass.getPrivateVariableofOuterClass();

        //test the private variable declared inside the static nested class
        OuterClass.accessStaticClass();
        /*
         * Inner Class Test
         * */

        //Declaration

        //first instantiate the outer class
        OuterClass outerClass = new OuterClass();

        //then instantiate the inner class
        OuterClass.InnerClass innerClassExample =  outerClass. new InnerClass();

        //test the non static private variable
        System.out.println(innerClassExample.getPrivateNonStaticVariableOfOuterClass()); 

    }

}
3
Pritam Banerjee

Ein Diagramm

enter image description here

Unterschied zwischen den Klassen static nested und non-static nested

  • Statisch verschachtelte Klassen haben keinen direkten Zugriff auf andere Mitglieder (nicht statische Variablen und Methoden) der einschließenden Klasse, da sie statisch sind und über ein Objekt auf die nicht statischen Mitglieder ihrer einschließenden Klasse zugreifen müssen. Das heißt, es kann nicht direkt auf nicht statische Member seiner einschließenden Klasse verweisen. Aufgrund dieser Einschränkung werden statisch verschachtelte Klassen selten verwendet.
  • Nicht statische verschachtelte Klassen (innere Klassen) haben Zugriff auf alle Mitglieder (statische und nicht statische Variablen und Methoden, einschließlich private) ihrer äußeren Klasse und können auf dieselbe Weise direkt auf sie verweisen wie andere nicht statische Mitglieder der äußeren Klasse Klasse machen.

Lesen Sie mehr hier

1
yoAlex5

Ich denke, dass keine der obigen Antworten Ihnen das reale Beispiel den Unterschied zwischen einer verschachtelten Klasse und einer statischen verschachtelten Klasse hinsichtlich des Anwendungsdesigns gibt. Der Hauptunterschied zwischen statisch verschachtelter Klasse und innerer Klasse besteht in der Möglichkeit, auf das Instanzfeld der äußeren Klasse zuzugreifen.

Werfen wir einen Blick auf die beiden folgenden Beispiele.

Statische Nest Klasse: Ein gutes Beispiel für statische verschachtelte Klassen ist Builder-Muster ( https://dzone.com/articles/design-patterns-the-builder-pattern ).

Für BankAccount verwenden wir eine statische verschachtelte Klasse, hauptsächlich weil

  1. Eine statische Verschachtelungsklasseninstanz könnte vor der äußeren Klasse erstellt werden.

  2. Im Builder-Muster ist der Builder eine Hilfsklasse, die zum Erstellen des Bankkontos verwendet wird.

  3. BankAccount.Builder ist nur mit BankAccount verbunden. Keine anderen Klassen sind mit BankAccount.Builder verwandt. Deshalb ist es besser, sie ohne Namenskonvention zusammen zu organisieren.
public class BankAccount {

    private long accountNumber;
    private String owner;
    ...

    public static class Builder {

    private long accountNumber;
    private String owner;
    ...

    static public Builder(long accountNumber) {
        this.accountNumber = accountNumber;
    }

    public Builder withOwner(String owner){
        this.owner = owner;
        return this; 
    }

    ...
    public BankAccount build(){
            BankAccount account = new BankAccount(); 
            account.accountNumber = this.accountNumber;
            account.owner = this.owner;
            ...
            return account;
        }
    }
}

Innere Klasse: Eine gebräuchliche Verwendung innerer Klassen besteht darin, einen Ereignishandler zu definieren. https://docs.Oracle.com/javase/tutorial/uiswing/events/generalrules.html

Für MyClass verwenden wir die innere Klasse, hauptsächlich weil:

  1. Innere Klasse MyAdapter muss auf das äußere Klassenmitglied zugreifen.

  2. In diesem Beispiel ist MyAdapter nur MyClass zugeordnet. Keine anderen Klassen sind mit MyAdapter verwandt. Daher ist es besser, sie ohne Namenskonvention zusammen zu organisieren

public class MyClass extends Applet {
    ...
        someObject.addMouseListener(new MyAdapter());
    ...
    class MyAdapter extends MouseAdapter {
        public void mouseClicked(MouseEvent e) {
            ...// Event listener implementation goes here...
            ...// change some outer class instance property depend on the event
        }
    }
}
1
Leogao

Mit der Programmiersprache Java können Sie eine Klasse innerhalb einer anderen Klasse definieren. Eine solche Klasse wird als verschachtelte Klasse bezeichnet und hier dargestellt:

class OuterClass {
...
class NestedClass {
    ...
    }
}

Geschachtelte Klassen werden in zwei Kategorien unterteilt: statisch und nicht statisch. Verschachtelte Klassen, die als statisch deklariert sind, werden als statische verschachtelte Klassen bezeichnet. Nicht statische verschachtelte Klassen werden als innere Klassen bezeichnet. Eine Sache, die wir beachten sollten, ist, dass nicht statische verschachtelte Klassen (innere Klassen) Zugriff auf andere Mitglieder der umgebenden Klasse haben, selbst wenn sie als privat deklariert sind. Statische verschachtelte Klassen haben nur dann Zugriff auf andere Mitglieder der umgebenden Klasse, wenn diese statisch sind. Sie kann nicht auf nicht statische Member der äußeren Klasse zugreifen .. Wie bei Klassenmethoden und -variablen wird eine statische verschachtelte Klasse mit ihrer äußeren Klasse verknüpft. Um beispielsweise ein Objekt für die statische verschachtelte Klasse zu erstellen, verwenden Sie diese Syntax:

OuterClass.StaticNestedClass nestedObject =
 new OuterClass.StaticNestedClass(); 

Um eine innere Klasse zu instanziieren, müssen Sie zuerst die äußere Klasse instanziieren. Dann erstellen Sie das innere Objekt innerhalb des äußeren Objekts mit dieser Syntax:

OuterClass.InnerClass innerObject = new OuterClass().new InnerClass();

Warum verwenden wir verschachtelte Klassen?

  1. Es ist eine Möglichkeit, Klassen logisch zu gruppieren, die nur an einer Stelle verwendet werden.
  2. Es erhöht die Einkapselung.
  3. Dies kann zu lesbarerem und wartungsfähigerem Code führen.

Quelle: Die Java ™ -Tutorials - Verschachtelte Klassen

0
Mithun Debnath

Zunächst einmal gibt es keine solche Klasse mit der Bezeichnung statische Klasse. Der Static-Modifizierer verwendet bei innerer Klasse (als geschachtelte Klasse bezeichnet), dass es sich um ein statisches Mitglied von Outer Class handelt. Dies bedeutet, dass wir wie auch auf andere statische Member zugreifen können Instanz der äußeren Klasse. (Welches ist der Vorteil von statisch ursprünglich.) 

Der Unterschied zwischen der Verwendung der verschachtelten Klasse und der regulären Inner-Klasse ist:

OuterClass.InnerClass inner = new OuterClass().new InnerClass();

Zuerst können wir Outerclass instanziieren, dann können wir auf Inner zugreifen.

Wenn Class jedoch verschachtelt ist, lautet die Syntax:

OuterClass.InnerClass inner = new OuterClass.InnerClass();

Welches verwendet die statische Syntax als normale Implementierung eines statischen Schlüsselworts.

0
Sohi