¿Cómo instanciar una clase interna no estática dentro de un método estático?

122

Tengo el siguiente código:

public class MyClass {

   class Inner {
     int s, e, p;
   }

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

Hasta esta parte, el código está bien, pero no puedo crear instancias 'in' dentro del método principal in = new Inner()como se muestra non static field cannot be referenced in static context.

¿De qué manera puedo hacerlo? No quiero que mi Innerclase sea estática .

Victor Mukherjee
fuente

Respuestas:

201

También debe tener una referencia a la otra clase externa.

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

Si Inner fuera estático, entonces sería

Inner inner = new MyClass.Inner();
RNJ
fuente
53
Esta respuesta solo cambió mi perspectiva de la vida. exterior.nuevo interior ()? Nunca lo consideré una posibilidad. O_O
AlbeyAmakiir
1
Para estática interna, ¿no puedes simplemente hacer Inner inner = new Inner ()?
Can Lu
1
@CanLu para crear un objeto para una clase anidada estática, use OuterClass.StaticNestedClass nestedObj = new OuterClass.StaticNestedClass(). Clases anidadas
LittleLittleQ
37

Una clase interna "regular" tiene un puntero oculto (implícito) a una instancia de clase externa. Esto permite que el compilador genere el código para perseguir el puntero por usted sin tener que escribirlo. Por ejemplo, si hay una variable "a" en la clase externa, entonces el código en su clase interna puede hacer "a = 0", pero el compilador generará código para "externalPointer.a = 0" manteniendo el puntero oculto debajo las portadas.

Esto significa que cuando crea una instancia de una clase interna, debe tener una instancia de una clase externa para vincularla. Si realiza esta creación dentro de un método de la clase externa, el compilador sabe usar "esto" como puntero implícito. Si desea vincular a alguna otra instancia externa, utilice una sintaxis especial "nueva" (consulte el fragmento de código a continuación).

Si hace que su clase interna sea "estática", entonces no hay un puntero oculto y su clase interna no puede hacer referencia a miembros de la clase externa. Una clase interna estática es idéntica a una clase regular, pero su nombre está dentro del padre.

Aquí hay un fragmento de código que demuestra la sintaxis para crear clases internas estáticas y no estáticas:

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
fuente
4

Si desea crear new Inner()desde un método, hágalo desde un método de instancia de la clase MyClass:

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

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

Alexei Kaigorodov es la respuesta correcta. Su solución le permite instanciar clases internas desde un método estático, como un main () de la misma clase. De lo contrario, no puede crear una instancia de una clase interna dentro de un método estático. No se compila. La solución de Alexei compila y le permite instanciar clases internas de un método estático. Las otras respuestas son notas al margen interesantes, pero no encuentro que respondan a la pregunta real.

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
fuente
Anexo: Puede crear instancias de clases internas estáticas a partir de métodos estáticos. Este tipo de código solo es necesario para crear instancias de clases internas no estáticas desde métodos estáticos.
Herbert Samuel Jennings III