Jak utworzyć instancję niestatycznej klasy wewnętrznej w ramach metody statycznej?

122

Mam następujący fragment kodu:

public class MyClass {

   class Inner {
     int s, e, p;
   }

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

Do tej części kod jest w porządku, ale nie jestem w stanie utworzyć wystąpienia „in” w głównej metodzie, tak in = new Inner()jak jest to pokazane non static field cannot be referenced in static context.

W jaki sposób mogę to zrobić? Nie chcę, aby moja Innerklasa była statyczna .

Victor Mukherjee
źródło

Odpowiedzi:

201

Musisz mieć również odniesienie do innej klasy zewnętrznej.

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

Gdyby Inner był statyczny, byłby

Inner inner = new MyClass.Inner();
RNJ
źródło
53
Ta odpowiedź właśnie zmieniła moje spojrzenie na życie. external.new Inner ()? Nigdy nawet nie rozważałem takiej możliwości. O_O
AlbeyAmakiir
1
W przypadku static inner, czy nie możesz po prostu zrobić Inner inner = new Inner ()?
Can Lu
1
@CanLu, aby utworzyć obiekt dla statycznej klasy zagnieżdżonej, użyj OuterClass.StaticNestedClass nestedObj = new OuterClass.StaticNestedClass(). Klasy zagnieżdżone
LittleLittleQ
37

„Zwykła” klasa wewnętrzna ma ukryty (niejawny) wskaźnik do instancji klasy Outer. Pozwala to kompilatorowi na wygenerowanie kodu do śledzenia wskaźnika bez konieczności wpisywania go. Na przykład, jeśli w klasie zewnętrznej znajduje się zmienna „a”, wówczas kod w klasie wewnętrznej może po prostu wykonać „a = 0”, ale kompilator wygeneruje kod dla „externalPointer.a = 0”, utrzymując ukryty wskaźnik pod osłony.

Oznacza to, że kiedy tworzysz instancję klasy wewnętrznej, musisz mieć instancję klasy zewnętrznej, z którą możesz ją połączyć. Jeśli zrobisz to wewnątrz metody klasy zewnętrznej, wówczas kompilator będzie wiedział, że używa "this" jako niejawnego wskaźnika. Jeśli chcesz utworzyć link do innej zewnętrznej instancji, użyj specjalnej „nowej” składni (zobacz fragment kodu poniżej).

Jeśli sprawisz, że Twoja klasa wewnętrzna stanie się „statyczna”, wtedy nie będzie ukrytego wskaźnika, a Twoja klasa wewnętrzna nie będzie mogła odwoływać się do członków klasy zewnętrznej. Statyczna klasa wewnętrzna jest identyczna z klasą zwykłą, ale jej nazwa jest objęta zakresem wewnątrz elementu nadrzędnego.

Oto fragment kodu, który demonstruje składnię tworzenia statycznych i niestatycznych klas wewnętrznych:

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
źródło
4

Jeśli chcesz stworzyć new Inner()z metody, zrób to z metody instancji klasy MyClass:

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

public static void main(String args[]){
  new MyClass().main();
}
Alexei Kaigorodov
źródło
0

Odpowiedź Aleksieja Kaigorodowa to właściwa odpowiedź. Jego rozwiązanie pozwala na tworzenie instancji klas wewnętrznych z poziomu metody statycznej, takiej jak main () tej samej klasy. W przeciwnym razie nie można utworzyć wystąpienia klasy wewnętrznej w ramach metody statycznej. Nie kompiluje się. Rozwiązanie Alexei'a nie kompiluje się i pozwala na tworzenie instancji klas wewnętrznych z metody statycznej. Pozostałe odpowiedzi są interesującymi uwagami dodatkowymi, ale nie uważam, aby odpowiadały one faktycznemu pytaniu.

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
źródło
Dodatek: można -można- utworzyć instancję statycznych klas wewnętrznych z metod statycznych. Ten rodzaj kodu jest potrzebny tylko do tworzenia instancji niestatycznych klas wewnętrznych z metod statycznych.
Herbert Samuel Jennings III