Come istanziare una classe interna non statica all'interno di un metodo statico?


122

Ho il seguente pezzo di codice:

public class MyClass {

   class Inner {
     int s, e, p;
   }

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

Fino a questa parte il codice va bene, ma non sono in grado di istanziare "in" all'interno del metodo principale come in = new Inner()mostrato non static field cannot be referenced in static context.

Qual è il modo in cui posso farlo? Non voglio rendere la mia Innerclasse statica .


Risposte:


201

Devi anche avere un riferimento all'altra classe esterna.

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

Se Inner fosse statico, allora lo sarebbe

Inner inner = new MyClass.Inner();

53
Questa risposta ha appena cambiato la mia visione della vita. esterno.new Interno ()? Non l'ho mai nemmeno considerata una possibilità. O_O
AlbeyAmakiir

1
Per static inner, non puoi semplicemente fare Inner inner = new Inner ()?
Can Lu

1
@CanLu per creare un oggetto per la classe annidata statica, utilizzare OuterClass.StaticNestedClass nestedObj = new OuterClass.StaticNestedClass(). Classi annidate
LittleLittleQ

37

Una classe interna "regolare" ha un puntatore nascosto (implicito) a un'istanza della classe Outer. Ciò consente al compilatore di generare il codice per inseguire il puntatore per te senza doverlo digitare. Ad esempio, se c'è una variabile "a" nella classe esterna, il codice nella classe interna può semplicemente fare "a = 0", ma il compilatore genererà codice per "outerPointer.a = 0" mantenendo il puntatore nascosto sotto le copertine.

Ciò significa che quando crei un'istanza di una classe interna devi avere un'istanza di una classe esterna a cui collegarla. Se fate questa creazione all'interno di un metodo della classe esterna, il compilatore sa di usare "this" come puntatore implicito. Se vuoi collegarti a qualche altra istanza esterna, usa una speciale sintassi "nuova" (vedi frammento di codice di seguito).

Se rendi la tua classe interna "statica", non ci sono puntatori nascosti e la tua classe interna non può fare riferimento ai membri della classe esterna. Una classe interna statica è identica a una classe normale, ma il suo nome ha l'ambito all'interno del genitore.

Ecco uno snippet di codice che dimostra la sintassi per la creazione di classi interne statiche e non statiche:

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

    }

}

4

Se vuoi creare new Inner()dall'interno di un metodo, fallo da un metodo di istanza della classe MyClass:

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

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

0

Quella di Alexei Kaigorodov è la risposta giusta. La sua soluzione consente di istanziare classi interne dall'interno di un metodo statico, come un main () della stessa classe. In caso contrario, non è possibile creare un'istanza di una classe interna all'interno di un metodo statico. Non si compila. La soluzione di Alexei si compila e ti consente di istanziare classi interne da un metodo statico. Le altre risposte sono interessanti note a margine, ma non le trovo rispondenti alla domanda reale.

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

Addendum: Puoi istanziare classi interne statiche da metodi statici. Questo tipo di codice è necessario solo per istanziare classi interne non statiche dall'interno di metodi statici.
Herbert Samuel Jennings III
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.