web-dev-qa-db-fra.com

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

J'ai le 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(), car elle affiche non static field cannot be referenced in static context. Comment puis-je le faire? Je ne veux pas rendre statique ma classe Inner.

112
Victor Mukherjee

Vous devez également faire 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();
186
RNJ

Une classe interne "normale" a un pointeur caché (implicite) vers une instance de classe Outer. Cela permet au compilateur de générer le code pour chasser le pointeur pour vous sans que vous ayez à le taper. Par exemple, s'il existe une variable "a" dans la classe externe, le code de votre classe interne peut simplement faire "a = 0", mais le compilateur générera du code pour "outerPointer.a = 0" en maintenant le pointeur masqué 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 pour la lier. Si vous effectuez cette création dans une méthode de la classe externe, le compilateur sait utiliser "ceci" comme pointeur implicite. Si vous souhaitez créer un lien vers une autre instance externe, utilisez une syntaxe "nouvelle" spéciale (voir l'extrait de code ci-dessous).

Si vous rendez votre classe interne "statique", 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 standard, mais son nom est défini dans le parent.

Voici un extrait de code qui illustre la syntaxe pour la 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

    }

}
37
ChrisCantrell

Si vous voulez 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();
}
3

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 est compilée et vous permet d'instancier des classes internes à partir d'une méthode statique. Les autres réponses sont des notes intéressantes, mais je ne les trouve pas sensibles à la question.

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