Wie instanziiere ich eine nicht statische innere Klasse innerhalb einer statischen Methode?

122

Ich habe den folgenden Code:

public class MyClass {

   class Inner {
     int s, e, p;
   }

   public static void main(String args[]) {
     Inner in;
   }
}

Bis zu diesem Teil ist der Code in Ordnung, aber ich bin nicht in der Lage, 'in' innerhalb der Hauptmethode zu instanziieren, wie in = new Inner()es gezeigt wird non static field cannot be referenced in static context.

Wie kann ich das machen? Ich möchte meine InnerKlasse nicht statisch machen .

Victor Mukherjee
quelle

Antworten:

201

Sie müssen auch einen Verweis auf die andere äußere Klasse haben.

Inner inner = new MyClass().new Inner();

Wenn Inner statisch wäre, wäre es das auch

Inner inner = new MyClass.Inner();
RNJ
quelle
53
Diese Antwort hat gerade meine Lebenseinstellung verändert. äußere.neue innere ()? Ich habe es nie für eine Möglichkeit gehalten. O_O
AlbeyAmakiir
1
Kannst du für statisches Inneres nicht einfach Inner Inner = New Inner () machen?
Kann Lu
1
Verwenden Sie @CanLu, um ein Objekt für eine statisch verschachtelte Klasse zu erstellen OuterClass.StaticNestedClass nestedObj = new OuterClass.StaticNestedClass(). Verschachtelte Klassen
LittleLittleQ
37

Eine "reguläre" innere Klasse hat einen versteckten (impliziten) Zeiger auf eine Instanz der äußeren Klasse. Auf diese Weise kann der Compiler den Code generieren, um den Zeiger für Sie zu verfolgen, ohne dass Sie ihn eingeben müssen. Wenn es beispielsweise eine Variable "a" in der äußeren Klasse gibt, kann der Code in Ihrer inneren Klasse nur "a = 0" ausführen, aber der Compiler generiert Code für "OuterPointer.a = 0", wobei der versteckte Zeiger unter beibehalten wird die Abdeckungen.

Das heißt, wenn Sie eine Instanz einer inneren Klasse erstellen, müssen Sie eine Instanz einer äußeren Klasse haben, mit der Sie sie verknüpfen können. Wenn Sie diese Erstellung innerhalb einer Methode der äußeren Klasse durchführen, kann der Compiler "this" als impliziten Zeiger verwenden. Wenn Sie eine Verknüpfung zu einer anderen äußeren Instanz herstellen möchten, verwenden Sie eine spezielle "neue" Syntax (siehe Codefragment unten).

Wenn Sie Ihre innere Klasse "statisch" machen, gibt es keinen versteckten Zeiger und Ihre innere Klasse kann nicht auf Mitglieder der äußeren Klasse verweisen. Eine statische innere Klasse ist identisch mit einer regulären Klasse, ihr Name ist jedoch innerhalb des übergeordneten Elements festgelegt.

Hier ist ein Codeausschnitt, der die Syntax zum Erstellen statischer und nicht statischer innerer Klassen demonstriert:

public class MyClass {

    int a,b,c; // Some members for MyClass

    static class InnerOne {
        int s,e,p;
        void clearA() {
            //a = 0;  Can't do this ... no outer pointer
        }
    }

    class InnerTwo {
        //MyClass parentPointer;      Hidden pointer to outer instance
        void clearA() {         
            a = 0;
            //outerPointer.a = 0      The compiler generates this code
        }       
    }

    void myClassMember() {
        // The compiler knows that "this" is the outer reference to give
        // to the new "two" instance.
        InnerTwo two = new InnerTwo(); //same as this.new InnerTwo()
    }

    public static void main(String args[]) {

        MyClass outer = new MyClass();

        InnerTwo x = outer.new InnerTwo(); // Have to set the hidden pointer
        InnerOne y = new InnerOne(); // a "static" inner has no hidden pointer
        InnerOne z = new MyClass.InnerOne(); // In other classes you have to spell out the scope

    }

}
ChrisCantrell
quelle
4

Wenn Sie new Inner()aus einer Methode heraus erstellen möchten , führen Sie dies aus einer Instanzmethode der Klasse aus MyClass:

public void main(){
  Inner inner = new Inner();
}

public static void main(String args[]){
  new MyClass().main();
}
Alexei Kaigorodov
quelle
0

Alexei Kaigorodovs ist die richtige Antwort. Mit seiner Lösung können Sie innere Klassen aus einer statischen Methode heraus instanziieren, z. B. aus main () derselben Klasse. Andernfalls können Sie eine innere Klasse innerhalb einer statischen Methode nicht instanziieren. Es wird nicht kompiliert. Die Lösung von Alexei wird kompiliert und ermöglicht es Ihnen, innere Klassen mithilfe einer statischen Methode zu instanziieren. Die anderen Antworten sind interessante Randnotizen, aber ich finde sie nicht als Antwort auf die eigentliche Frage.

import java.awt.Graphics;
import java.awt.Color;
import javax.swing.JPanel;
import javax.swing.JFrame;

public class Example {
    public class InnerClass extends JPanel {
        public void paint(Graphics g) {
            g.setColor(Color.BLACK);
            g.fillRect(getX(),getY(),getWidth(),getHeight());
            g.setColor(Color.RED);
            g.fillRect(5, 20, 195, 20);
            g.setColor(Color.BLACK);
            g.drawString("This was written by an inner class.", 10, 35);
        }
    }

    public void demonstrate() {
        InnerClass sc = new InnerClass();//<---this is key
        JFrame jf = new JFrame();
        jf.add(sc);
        jf.setSize(220, 130);
        jf.setLocation(450, 450);
        jf.show();
    }

    public static void main(String[] params) {
        Example e = new Example();//<---so is this
        e.demonstrate();//<---and this is also key
    }
}
Herbert Samuel Jennings III
quelle
Nachtrag: Sie können statische innere Klassen aus statischen Methoden instanziieren. Diese Art von Code wird nur benötigt, um nicht statische innere Klassen innerhalb statischer Methoden zu instanziieren.
Herbert Samuel Jennings III