Comment instancier une classe interne non statique dans une méthode statique?

122

J'ai le morceau de code suivant:

public class MyClass {

   class Inner {
     int s, e, p;
   }

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

Jusqu'à cette partie, le code est correct, mais je ne suis pas en mesure d'instancier «in» dans la méthode principale comme in = new Inner()il est montré non static field cannot be referenced in static context.

Comment puis-je le faire? Je ne veux pas rendre ma Innerclasse statique .

Victor Mukherjee
la source

Réponses:

201

Vous devez également avoir une référence à l'autre classe externe.

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

Si Inner était statique alors ce serait

Inner inner = new MyClass.Inner();
RNJ
la source
53
Cette réponse a changé ma vision de la vie. external.new Inner ()? Jamais même considéré comme une possibilité. O_O
AlbeyAmakiir
1
Pour un intérieur statique, ne pouvez-vous pas simplement faire Inner inner = new Inner ()?
Can Lu
1
@CanLu pour créer un objet pour la classe imbriquée statique, utilisez OuterClass.StaticNestedClass nestedObj = new OuterClass.StaticNestedClass(). Classes imbriquées
LittleLittleQ
37

Une classe interne «régulière» a un pointeur caché (implicite) vers une instance de classe externe. Cela permet au compilateur de générer le code pour poursuivre le pointeur pour vous sans que vous ayez à le taper. Par exemple, s'il y a une variable «a» dans la classe externe, alors le code de votre classe interne peut simplement faire «a = 0», mais le compilateur générera du code pour «externalPointer.a = 0» en maintenant le pointeur caché sous les couvertures.

Cela signifie que lorsque vous créez une instance d'une classe interne, vous devez avoir une instance d'une classe externe à laquelle la lier. Si vous effectuez cette création dans une méthode de la classe externe, le compilateur sait utiliser "this" comme pointeur implicite. Si vous souhaitez créer un lien vers une autre instance externe, vous utilisez une syntaxe "nouvelle" spéciale (voir l'extrait de code ci-dessous).

Si vous rendez votre classe interne "statique", alors il n'y a pas de pointeur caché et votre classe interne ne peut pas référencer les membres de la classe externe. Une classe interne statique est identique à une classe régulière, mais son nom est limité à l'intérieur du parent.

Voici un extrait de code qui illustre la syntaxe de création de classes internes statiques et non statiques:

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
la source
4

Si vous souhaitez créer à new Inner()partir d'une méthode, faites-le à partir d'une méthode d'instance de la classe MyClass:

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

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

Alexei Kaigorodov est la bonne réponse. Sa solution vous permet d'instancier des classes internes à partir d'une méthode statique, telle qu'un main () de la même classe. Sinon, vous ne pouvez pas instancier une classe interne dans une méthode statique. Il ne compile pas. La solution d'Alexei compile et vous permet d'instancier des classes internes à partir d'une méthode statique. Les autres réponses sont des notes d'accompagnement intéressantes, mais je ne les trouve pas adaptées à la question réelle.

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
la source
Addendum: Vous -pouvez- instancier des classes internes statiques à partir de méthodes statiques. Ce type de code n'est nécessaire que pour instancier des classes internes non statiques à partir de méthodes statiques.
Herbert Samuel Jennings III