Como instanciar classe interna não estática dentro de um método estático?

122

Eu tenho o seguinte pedaço de código:

public class MyClass {

   class Inner {
     int s, e, p;
   }

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

Até essa parte, o código é bom, mas não consigo instanciar 'in' dentro do método principal, como in = new Inner()ele está mostrando non static field cannot be referenced in static context.

Como posso fazer isso? Eu não quero fazer o meuInner classe estática .

Victor Mukherjee
fonte

Respostas:

201

Você também deve ter uma referência à outra classe externa.

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

Se Inner fosse estático, seria

Inner inner = new MyClass.Inner();
RNJ
fonte
53
Essa resposta acabou de mudar minha visão da vida. outer.new Inner ()? Nunca sequer considerou isso uma possibilidade. O_O
AlbeyAmakiir
1
Para interior estático, você não pode simplesmente fazer Inner inner = new Inner ()?
Pode Lu
1
@ Canan para criar um objeto para a classe aninhada estática, use OuterClass.StaticNestedClass nestedObj = new OuterClass.StaticNestedClass(). Classes aninhadas
LittleLittleQ
37

Uma classe interna "regular" possui um ponteiro oculto (implícito) para uma instância de classe externa. Isso permite que o compilador gere o código para perseguir o ponteiro para você sem precisar digitá-lo. Por exemplo, se houver uma variável "a" na classe externa, o código na sua classe interna poderá fazer "a = 0", mas o compilador gerará código para "outerPointer.a = 0" mantendo o ponteiro oculto em As tampas.

Isso significa que, quando você cria uma instância de uma classe interna, é necessário ter uma instância de uma classe externa para vinculá-la. Se você criar essa criação dentro de um método da classe externa, o compilador saberá usar "this" como ponteiro implícito. Se você deseja vincular a outra instância externa, use uma sintaxe "nova" especial (consulte o trecho de código abaixo).

Se você tornar sua classe interna "estática", não haverá ponteiro oculto e sua classe interna não poderá referenciar membros da classe externa. Uma classe interna estática é idêntica a uma classe regular, mas seu nome é definido dentro do pai.

Aqui está um trecho de código que demonstra a sintaxe para criar classes internas estáticas e não 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
fonte
4

Se você deseja criar new Inner()de dentro de um método, faça-o a partir de um método de instância da classe MyClass:

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

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

Alexei Kaigorodov é a resposta certa. Sua solução permite instanciar classes internas a partir de um método estático, como main () da mesma classe. Caso contrário, você não poderá instanciar uma classe interna dentro de um método estático. Não compila. A solução de Alexei é compilada e permite instanciar classes internas a partir de um método estático. As outras respostas são notas secundárias interessantes, mas não as acho responsivas à pergunta 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
fonte
Adendo: Você pode instanciar classes internas estáticas a partir de métodos estáticos. Esse tipo de código é necessário apenas para instanciar classes internas não estáticas de dentro de métodos estáticos.
Herbert Samuel Jennings III