静的メソッド内で非静的内部クラスをインスタンス化する方法は?


122

次のコードがあります。

public class MyClass {

   class Inner {
     int s, e, p;
   }

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

この部分までのコードは大丈夫ですが、私のようなmainメソッド内「で」インスタンス化することはできませんよin = new Inner()、それが表示されているようnon static field cannot be referenced in static context

どうすればよいですか?Innerクラスを静的にしたくありません。


回答:


201

他の外部クラスへの参照も必要です。

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

インナーが静的であれば、それは

Inner inner = new MyClass.Inner();

53
この答えは私の人生観を変えました。outer.new Inner()?それを可能性とさえ考えなかった。O_O
AlbeyAmakiir

1
静的内部の場合、単にInner inner = new Inner()を実行できませんか?
Luは

1
@CanLuは、入れ子の静的クラスのオブジェクトを作成するには、を使用しますOuterClass.StaticNestedClass nestedObj = new OuterClass.StaticNestedClass()ネストされたクラス
LittleLittleQ

37

「通常の」内部クラスには、外部クラスインスタンスへの隠された(暗黙の)ポインタがあります。これにより、コンパイラーは、ユーザーが入力することなく、ポインターを追跡するコードを生成できます。たとえば、外部クラスに変数「a」がある場合、内部クラスのコードは「a = 0」を実行できますが、コンパイラは「outerPointer.a = 0」のコードを生成し、その下に隠しポインタを維持します。カバー。

つまり、内部クラスのインスタンスを作成する場合、リンクする外部クラスのインスタンスが必要です。外部クラスのメソッド内でこの作成を行う場合、コンパイラーは暗黙のポインターとして「this」を使用することを認識しています。他の外部インスタンスにリンクする場合は、特別な「新しい」構文を使用します(以下のコードスニペットを参照)。

内部クラスを「静的」にすると、非表示のポインターはなくなり、内部クラスは外部クラスのメンバーを参照できなくなります。静的内部クラスは通常のクラスと同じですが、その名前のスコープは親の内部です。

以下は、静的および非静的内部クラスを作成するための構文を示すコードのスニペットです。

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

new Inner()メソッド内から作成する場合は、クラスのインスタンスメソッドから作成しますMyClass

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

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

0

アレクセイ・カイゴロドフが正解です。彼のソリューションでは、同じクラスのmain()などの静的メソッド内から内部クラスをインスタンス化できます。そうしないと、静的メソッド内で内部クラスをインスタンス化できません。コンパイルされません。Alexeiのソリューションはコンパイルを行い、静的メソッドから内部クラスをインスタンス化できるようにします。他の回答は興味深い副注ですが、実際の質問に応答することはできません。

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

補遺:静的メソッドから静的内部クラスをインスタンス化できます。この種のコードは、静的メソッド内から非静的内部クラスをインスタンス化する場合にのみ必要です。
ハーバートサミュエルジェニングスIII
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.