zugriff - statische klassen java




Java innere Klasse und statische geschachtelte Klasse (16)

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


Aus dem Java-Tutorial :

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

Auf statische verschachtelte Klassen wird über den einschließenden Klassennamen zugegriffen:

OuterClass.StaticNestedClass

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

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

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

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

Eine Instanz von InnerClass kann nur innerhalb einer Instanz von OuterClass existieren und hat direkten Zugriff auf die Methoden und Felder ihrer einschließ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 - Verschachtelte Klassen

Der Vollständigkeit halber sei erwähnt, dass es auch eine innere Klasse ohne umschließ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 keine umschließende Instanz hat.


Das Java-Tutorial sagt :

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

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

Klassen können ad infinitum verschachtelt werden, zB Klasse A kann Klasse B enthalten, die Klasse C enthält, die Klasse D usw. enthält. Jedoch ist mehr als eine Ebene der Klassenverschachtelung selten, da sie im allgemeinen schlecht gestaltet ist.

Es gibt drei Gründe, warum Sie eine geschachtelte Klasse erstellen könnten:

  • Organisation: Manchmal scheint es am sinnvollsten, eine Klasse in den Namespace einer anderen Klasse zu sortieren, besonders wenn sie in keinem anderen Kontext verwendet wird
  • access: geschachtelte Klassen haben speziellen Zugriff auf die Variablen / Felder ihrer enthaltenden Klassen (genau welche Variablen / Felder von der Art der geschachtelten Klasse abhängen, ob innerlich oder statisch).
  • Bequemlichkeit: Eine neue Datei für jeden neuen Typ erstellen zu müssen, ist wiederum lästig, besonders wenn der Typ nur in einem Kontext verwendet wird

Es gibt vier Arten von geschachtelten Klassen in Java . In Kürze sind sie:

  • statische Klasse : als statisches Mitglied einer anderen Klasse deklariert
  • innere Klasse : wird als Instanzmitglied einer anderen Klasse deklariert
  • lokale innere Klasse : innerhalb einer Instanzmethode einer anderen Klasse deklariert
  • anonyme innere Klasse : Wie eine lokale innere Klasse, aber als ein Ausdruck geschrieben, der ein einmaliges Objekt zurückgibt

Lassen Sie mich 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 Mitglieder ist eine solche Klasse wirklich nur ein Aufhänger, der die enthaltene Klasse als Namespace verwendet, z. B. die Klasse Goat , die als statisches Mitglied der Klasse Rhino in der Paketpizza deklariert ist, ist unter dem Namen pizza.Rhino.Goat bekannt .

package pizza;

public class Rhino {

    ...

    public static class Goat {
        ...
    }
}

Offen gesagt, statische Klassen sind ein ziemlich wertloses Feature, da Klassen bereits in Pakete unterteilt sind. Der einzig wirklich denkbare Grund, eine statische Klasse zu erstellen, besteht darin, dass eine solche Klasse Zugriff auf die privaten statischen Member ihrer enthaltenden Klasse hat, aber ich finde, dass dies eine ziemlich lahme Begründung für das Vorhandensein der statischen Klassenfunktion ist.


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 als durch den Klassennamen pizza.Rhino.Goat qualifiziert bezeichnet , aber innerhalb der enthaltenen Klasse kann sie durch ihren einfachen Namen erkannt werden. Jede Instanz einer inneren Klasse ist jedoch an eine bestimmte Instanz ihrer enthaltenden Klasse gebunden: oben ist die in jerry erstellte Ziege implizit mit der Rhino- Instanz in jerry verknüpft . 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 den inneren Typ nur als Ziege in der seltsamen neuen Syntax bezeichnen: Java leitet den enthaltenden Typ aus dem Rhino- Teil ab. Und, ja, new Rhino.Goat () wäre mir auch sinnvoller geworden.)

Was bringt uns das? Nun, die innere Klasseninstanz hat Zugriff auf die Instanzmitglieder der enthaltenden Klasseninstanz. Auf diese umschließenden Instanzenmitglieder wird innerhalb der inneren Klasse nur über ihre einfachen Namen verwiesen, nicht über diese ( dies bezieht sich in der inneren Klasse auf die innere Klasseninstanz und 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 als Rhino.this auf die Klasse verweisen, die sie enthält, und Sie können damit auf ihre Member verweisen, z . B. 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 ihrer containing-Methode bekannt, so dass sie nur instanziiert werden kann und auf ihre Mitglieder innerhalb ihrer containing-Methode zugegriffen werden kann. Die Verstärkung besteht darin, dass eine lokale innere Klasseninstanz mit den letzten lokalen Variablen ihrer enthaltenden Methode verknüpft ist und auf diese zugreifen kann. Wenn die Instanz eine letzte lokale Methode ihrer containing-Methode verwendet, behält die Variable den Wert bei, den sie zum Zeitpunkt der Erstellung der Instanz beibehielt, selbst wenn die Variable den Gültigkeitsbereich verlassen hat (dies ist tatsächlich die primitive, eingeschränkte 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. (Seien Sie jedoch klar, dass die eigenen Mitglieder Zugriffsebenen wie in einer normalen Klasse haben.)

Wenn eine lokale innere Klasse in einer Instanzmethode deklariert ist, ist eine Instanz der inneren Klasse an die Instanz gebunden, die von der Methode der behaltenden Methode zum Zeitpunkt der Erzeugung der Instanz gehalten wird, und so sind die Instanzmitglieder der enthaltenen Klasse wie in einer Instanz zugänglich innere Klasse. Eine lokale innere Klasse wird einfach über ihren Namen instanziiert, zB wird die lokale innere Klasse Cat als neues Cat () instanziiert, nicht wie erwartet neu this.Cat ().


Anonyme innere Klassen

Eine anonyme innere Klasse ist eine syntaktisch bequeme Art, eine lokale innere Klasse zu schreiben. In den meisten Fällen wird eine lokale innere Klasse höchstens einmal jedes Mal instanziiert, wenn ihre containing-Methode ausgeführt wird. 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 (umso weniger hilfreich Namen, die Ihr Code enthält, desto besser). Eine anonyme innere Klasse erlaubt beides:

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

Dies ist ein Ausdruck, der eine neue Instanz einer unbenannten Klasse zurückgibt, die ParentClassName erweitert . Sie können keinen eigenen Konstruktor angeben. vielmehr wird implizit einer geliefert, der einfach den Superkonstruktor aufruft, also müssen die gelieferten Argumente zum Superkonstruktor passen. (Wenn der Elternteil mehrere Konstruktoren enthält, wird der "einfachste" als "einfachste" bezeichnet, wie durch ein ziemlich komplexes Regelwerk bestimmt, das nicht im Detail zu lernen lohnt - achten Sie nur darauf, was NetBeans oder Eclipse Ihnen sagen.)

Alternativ können Sie eine zu implementierende Schnittstelle angeben:

new *InterfaceName*() {*members*}

Eine solche Deklaration erstellt eine neue Instanz einer unbenannten Klasse, die Object erweitert und InterfaceName implementiert. Auch hier können Sie keinen eigenen Konstruktor angeben. In diesem Fall liefert Java implizit einen Konstruktor "no-arg, do-nothing" (daher gibt es in diesem Fall niemals Konstruktorargumente).

Obwohl Sie einer anonymen inneren Klasse keinen Konstruktor geben können, können Sie dennoch beliebige Setups verwenden, die einen Initialisierungsblock verwenden (ein {} -Block außerhalb jeder Methode).

Machen Sie sich klar, dass eine anonyme innere Klasse einfach eine weniger flexible Möglichkeit ist, eine lokale innere Klasse mit einer Instanz zu erstellen. Wenn Sie eine lokale innere Klasse möchten, die mehrere Schnittstellen implementiert oder die Schnittstellen implementiert, während Sie eine andere Klasse als Object erweitern oder einen eigenen Konstruktor angeben, müssen Sie eine reguläre benannte lokale innere Klasse erstellen.


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, hören auch die inneren Klasseninstanzen auf zu existieren.

Die statische verschachtelte Klasse hat keine konkrete Instanz. Es wird nur geladen, wenn es zum ersten Mal verwendet wird (genau wie die statischen Methoden). Es ist eine vollständig 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 sie nehmen keinen Heap / Stack-Speicher, weil es nicht notwendig ist, eine Instanz einer solchen Klasse zu erstellen. Daher besteht die Faustregel darin, zu versuchen, die statische verschachtelte Klasse mit einem möglichst begrenzten Umfang zu definieren (privat> = class> = protected> = public) und dann in die innere Klasse zu konvertieren (durch Entfernen der "statischen" Kennung) und zu lockern der Umfang, wenn es wirklich notwendig ist.


Die Verwendung verschachtelter statischer Klassen, die in bestimmten Situationen nützlich sein können, ist subtil.

Während statische Attribute instanziiert werden, bevor die Klasse über ihren Konstruktor instanziiert wird, scheinen statische Attribute in verschachtelten statischen Klassen erst dann instanziiert zu werden, nachdem der Konstruktor der Klasse aufgerufen wurde, oder zumindest nicht bis nach der ersten Referenzierung der Attribute, selbst wenn Sie sind als "endgültig" gekennzeichnet.

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 'nested' und 'innerItem' beide als 'statisch final' deklariert sind. Die Einstellung von nested.innerItem findet erst nach dem Instanziieren der Klasse statt (oder zumindest nicht vor dem ersten Verweis auf das verschachtelte statische Element), wie Sie selbst sehen können, indem Sie die Zeilen, auf die ich mich beziehe, kommentieren und auskommentieren. über. Das gleiche gilt nicht für das 'äußere Element'.

Zumindest sehe ich das in Java 6.0.


Geschachtelte Klasse: Klasse innerhalb der Klasse

Typen:

  1. Statisch geschachtelte Klasse
  2. Nicht-statische geschachtelte Klasse [Innere Klasse]

Unterschied:

Nicht-statische geschachtelte Klasse [Innere Klasse]

In nicht statischen geschachtelten Klassen existiert das Objekt der inneren Klasse innerhalb des Objekts der äußeren Klasse. Damit ist das Datenelement der äußeren Klasse für die innere Klasse zugänglich. Um ein Objekt der inneren Klasse zu erzeugen, müssen wir zuerst das Objekt der äußeren Klasse erzeugen.

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

Statisch geschachtelte Klasse

Im statischen geschachtelten Klassenobjekt der inneren Klasse wird kein Objekt der äußeren Klasse benötigt, weil das Wort "statisch" anzeigt, dass kein Objekt erzeugt werden muss.

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

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

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

Hier sind die wichtigsten Unterschiede und Ähnlichkeiten zwischen der Java-internen Klasse und der statischen geschachtelten Klasse.

Ich hoffe es hilft!

Innere Klasse

  • Kann sowohl auf Instanzklassen als auch auf statische Methoden und Felder zugreifen
  • Verknüpft mit der Instanz der umschließenden Klasse , um sie instanziieren zu müssen, benötigt sie zuerst eine Instanz der äußeren Klasse (notice new keyword place):

    Outerclass.InnerClass innerObject = outerObject.new Innerclass();
    
  • Kann keine statischen Elemente selbst definieren

  • Kann keine Klassen- oder Interface- Deklaration haben

Statisch geschachtelte Klasse

  • Auf externe Klasseninstanzmethoden oder -felder kann nicht zugegriffen werden

  • Nicht mit einer Instanz der umschließenden Klasse verknüpft, also um sie zu instanziieren:

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

Ähnlichkeiten

  • Beide Inner-Klassen können auf private Felder und Methoden der äußeren Klasse zugreifen
  • Auch die Outer-Klasse hat Zugriff auf private Felder und Methoden innerer Klassen
  • Beide Klassen können einen privaten, geschützten oder öffentlichen Zugriffsmodifikator haben

Warum verschachtelte Klassen verwenden?

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

  • Es ist eine Möglichkeit, Klassen logisch zu gruppieren, die nur an einer Stelle verwendet werden: Wenn eine Klasse nur für eine andere Klasse nützlich ist, dann ist es logisch, sie in diese Klasse einzubetten und sie zusammen zu halten. Die Verschachtelung solcher "Hilfsklassen" macht ihr Paket schlanker.

  • Es erhöht die Kapselung: Betrachten Sie zwei Klassen der obersten Ebene, A und B, wobei B Zugriff auf Member von A benötigt, die andernfalls als privat deklariert würden. Durch das Verstecken der Klasse B innerhalb 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 sein.

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


Ich denke, die Konvention, die allgemein befolgt wird, ist diese:

  • Die statische Klasse innerhalb einer Top-Level-Klasse ist eine geschachtelte Klasse
  • Nicht statische Klasse innerhalb einer Top-Level-Klasse ist eine innere Klasse , die noch zwei weitere Formen hat:
    • Lokale Klasse - benannte Klassen, die innerhalb eines Blocks wie eine Methode oder ein Konstruktor-Body deklariert sind
    • anonyme Klasse - unbenannte Klassen, deren Instanzen in Ausdrücken und Anweisungen erstellt werden

Allerdings sind einige andere Punkte zu erinnern :

  • Top-Level-Klassen und statische geschachtelte Klassen sind semantisch gleich, außer dass sie im Falle einer statischen geschachtelten Klasse einen statischen Verweis auf private statische Felder / Methoden der Outer-Klasse [übergeordnet] und umgekehrt bereitstellen können.

  • Innere Klassen haben Zugriff auf Instanzvariablen der einschließenden Instanz der Outer [parent] -Klasse. Nicht alle inneren Klassen haben jedoch umschließende Instanzen, zum Beispiel 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, und es gibt keine weitere Klausel, um eine andere Klasse zu erweitern oder weitere Schnittstellen zu implementieren. Damit,

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

Ich fühle, dass die größere Frage offen bleibt, welche zu verwenden ist und wann? Nun, das hängt hauptsächlich davon ab, mit welchem ​​Szenario du es zu tun hast, aber die Antwort von @jrudolph zu lesen, kann dir helfen, eine Entscheidung zu treffen.


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

Um die Bedingungen richtig zu machen:

  • Eine geschachtelte Klasse ist eine Klasse, die in einer anderen Klasse auf Quellcodeebene enthalten ist.
  • Es ist statisch, wenn Sie es mit dem statischen Modifikator deklarieren.
  • Eine nicht statische geschachtelte Klasse wird innere Klasse genannt. (Ich bleibe bei der nicht statischen geschachtelten Klasse.)

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

Sie verwenden statische geschachtelte Klassen, wenn Sie nur Ihre Klassen zusammenhalten möchten, wenn sie topisch zusammen gehören oder wenn die geschachtelte Klasse ausschließlich in der einschließenden Klasse verwendet wird. Es gibt keinen semantischen Unterschied zwischen einer statischen verschachtelten Klasse und jeder anderen Klasse.

Nicht-statische verschachtelte Klassen sind ein anderes Biest. Ähnlich wie anonyme innere Klassen sind solche verschachtelten Klassen tatsächlich Closures. Das bedeutet, dass sie ihren umgebenden Bereich und ihre umschließende Instanz erfassen und zugänglich machen. Vielleicht wird ein Beispiel das klären. Sieh diesen Stummel 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 einen Verweis von einem untergeordneten Element auf den übergeordneten Container haben. Mit einer nicht statischen geschachtelten Klasse funktioniert dies ohne etwas Arbeit. Sie können auf die umschließende Instanz von Container mit der Syntax Container.this zugreifen.

Weitere Hardcore-Erklärungen folgen:

Wenn Sie sich die Java-Bytecodes anschauen, die der Compiler für eine (nicht-statische) verschachtelte Klasse generiert, könnte es 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 können, 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 umschließende Instanz anzugeben. Sie können diesen Parameter nicht in der Quelle anzeigen, aber der Compiler generiert ihn implizit für eine verschachtelte Klasse.

Martins Beispiel

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

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

new InnerClass(outerObject)

Der Vollständigkeit halber:

Eine anonyme Klasse ist ein perfektes Beispiel für eine nicht-statische geschachtelte Klasse, der kein Name zugeordnet ist und auf die später nicht verwiesen werden kann.


Im Fall der Erstellung der Instanz wird die Instanz der nicht statischen inneren Klasse mit der Referenz des Objekts der äußeren Klasse erstellt, in der sie definiert ist. Das bedeutet, dass es eine Instanz enthält. Die Instanz der statischen inneren Klasse wird jedoch mit der Referenz der äußeren Klasse und nicht mit der Referenz des Objekts der äußeren Klasse erstellt. Dies bedeutet, dass es keine Instanz enthält.

Beispielsweise:

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….
  }
}

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

Edit: If you actually meant inner vs anonymous... an inner class is just a class defined within a class such as:

public class A {
    public class B {
    }
}

Whereas an anonymous class is an extension of a class defined anonymously, so no actual "class is defined, as in:

public class A {
}

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

Further Edit:

Wikipedia claims there is a difference in Java, but I've been working with Java for 8 years, and it's the first I heard such a distinction... not to mention there are no references there to back up the claim... bottom line, an inner class is a class defined within a class (static or not), and nested is just another term to mean the same thing.

There is a subtle difference between static and non-static nested class... basically non-static inner classes have implicit access to instance fields and methods of the enclosing class (thus they cannot be constructed in a static context, it will be a compiler error). Static nested classes, on the other hand, don't have implicit access to instance fields and methods, and CAN be constructed in a static context.


Targeting learner, who are novice to Java and/or Nested Classes

Nested classes can be either:
1. Static Nested classes.
2. Non Static Nested classes. (also known as Inner classes ) =>Please remember this


1.Inner classes
Beispiel:

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


Inner classes are subsets of nested classes:

  • inner class is a specific type of nested class
  • inner classes are subsets of nested classes
  • You can say that an inner class is also a nested class, but you can NOT say that a nested class is also an inner class .

Specialty of Inner class:

  • instance of an inner class has access to all of the members of the outer class, even those that are marked “private”


2.Static Nested Classes:
Beispiel:

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

Case 1:Instantiating a static nested class from a non-enclosing class

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"
  }
}

Case 2:Instantiating a static nested class from an enclosing class

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"
  }

}

Specialty of Static classes:

  • Static inner class would only have access to the static members of the outer class, and have no access to non-static members.

Fazit:
Question: What is the main difference between a inner class and a static nested class in Java?
Answer: just go through specifics of each class mentioned above.


Inner class and nested static class in Java both are classes declared inside another class, known as top level class in Java. In Java terminology, If you declare a nested class static, it will called nested static class in Java while non static nested class are simply referred as Inner Class.

What is Inner Class in Java?

Any class which is not a top level or declared inside another class is known as nested class and out of those nested classes, class which are declared non static are known as Inner class in Java. there are three kinds of Inner class in Java:

1) Local inner class - is declared inside a code block or method.
2) Anonymous inner class - is a class which doesn't have name to reference and initialized at same place where it gets created.
3) Member inner class - is declared as non static member of outer class.

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");
        }
    }
}

What is nested static class in Java?

Nested static class is another class which is declared inside a class as member and made static. Nested static class is also declared as member of outer class and can be make private, public or protected like any other member. One of the main benefit of nested static class over inner class is that instance of nested static class is not attached to any enclosing instance of Outer class. You also don't need any instance of Outer class to create instance of nested static class in Java .

1) It can access static data members of outer class including private.
2) Static nested class cannot access non-static (instance) data member or method .

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: Inner class and nested Static Class in Java with Example


I have illustrated various possible correct and error scenario which can occur in java code.

    class Outter1 {

        String OutStr;

        Outter1(String str) {
            OutStr = str;
        }

        public void NonStaticMethod(String st)  {

            String temp1 = "ashish";
            final String  tempFinal1 = "ashish"; 

            //  below static attribute not permitted
            // static String tempStatic1 = "static";    

            //  below static with final attribute not permitted         
            // static final String  tempStatic1 = "ashish";  

            // synchronized keyword is not permitted below          
            class localInnerNonStatic1 {            

                synchronized    public void innerMethod(String str11) {
                    str11 = temp1 +" sharma";
                    System.out.println("innerMethod ===> "+str11);
                }

                /* 
        //  static method with final not permitted
          public static void innerStaticMethod(String str11) { 

                    str11 = temp1 +" india";
                    System.out.println("innerMethod ===> "+str11);
                }*/
            }

            // static class not permitted below
            //  static class localInnerStatic1 {   }                            

        }

        public static  void StaticMethod(String st)     {

            String temp1 = "ashish";
            final String  tempFinal1 = "ashish"; 

            // static attribute not permitted below
            //static String tempStatic1 = "static";     

            //  static with final attribute not permitted below
            // static final String  tempStatic1 = "ashish";                         

            class localInnerNonStatic1 {
                public void innerMethod(String str11) {
                    str11 = temp1 +" sharma";
                    System.out.println("innerMethod ===> "+str11);
                }

                /*
    // static method with final not permitted
    public static void innerStaticMethod(String str11) {  
                    str11 = temp1 +" india";
                    System.out.println("innerMethod ===> "+str11);
                }*/
            }

            // static class not permitted below
            //  static class localInnerStatic1 {   }    

        }

        // synchronized keyword is not permitted
        static  class inner1 {          

            static String  temp1 = "ashish";
            String  tempNonStatic = "ashish";
            // class localInner1 {

            public void innerMethod(String str11) {
                str11 = temp1 +" sharma";
                str11 = str11+ tempNonStatic +" sharma";
                System.out.println("innerMethod ===> "+str11);
            }

            public static void innerStaticMethod(String str11) {
                //  error in below step
                str11 = temp1 +" india";    
                //str11 = str11+ tempNonStatic +" sharma";
                System.out.println("innerMethod ===> "+str11);
            }
            //}
        }

        //synchronized keyword is not permitted below
        class innerNonStatic1 {             

//This is important we have to keep final with static modifier in non
// static innerclass below
            static final String  temp1 = "ashish";  
            String  tempNonStatic = "ashish";
            // class localInner1 {

            synchronized    public void innerMethod(String str11) {
                tempNonStatic = tempNonStatic +" ...";
                str11 = temp1 +" sharma";
                str11 = str11+ tempNonStatic +" sharma";
                System.out.println("innerMethod ===> "+str11);
            }

            /*
            //  error in below step
            public static void innerStaticMethod(String str11) {   
                            //  error in below step
                            // str11 = tempNonStatic +" india";                     
                            str11 = temp1 +" india";
                            System.out.println("innerMethod ===> "+str11);
                        }*/
                    //}
                }
    }

I think people here should notice to Poster that : Static Nest Class just only the first inner class. Beispielsweise:

 public static class A {} //ERROR

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

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

 }

So, summarize, static class doesn't depend which class its contains. So, they cannot in normal class. (because normal class need an instance).


The following is an example of static nested class and 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()); 

    }

}

When we declare static member class inside a class, it is known as top level nested class or a static nested class. It can be demonstrated as below :

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());
    }
}

When we declare non-static member class inside a class it is known as inner class. Inner class can be demonstrated as below :

    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);
        }
    }
}




inner-classes