web-dev-qa-db-ja.com

Java - Foo型の外側のインスタンスにアクセスできない

次のようなコードがあります。

class Hello {
    class Thing {
        public int size;

        Thing() {
            size = 0;
        }
    }

    public static void main(String[] args) {
        Thing thing1 = new Thing();
        System.out.println("Hello, World!");
    }
}

私はThingが何もしないことを知っていますが、私のHello、Worldプログラムはそれなしでうまくコンパイルできます。私に失敗しているのは私の定義済みクラスだけです。

そしてそれはコンパイルを拒否します。新しいThingを作成した行にNo enclosing instance of type Hello is accessible."が表示されます。私はどちらかと思います:

  1. システムレベルの問題(DrJavaまたは私のJavaインストール)があります。
  2. Javaで作業プログラムを作成する方法について基本的な誤解があります。

何か案は?

289
coolpapa

static class Thingはあなたのプログラムを動かします。

Thingを内部クラスとして持っています。これは(定義上はHelloの特定のインスタンスに関連付けられています(これを使用または参照していない場合でも))。つまり、new Thing();を指定せずに言うとエラーになります。スコープ内の特定のHelloインスタンス.

代わりにそれを静的クラスとして宣言した場合、それは "ネストされた"クラスです。これは特定のHelloインスタンスを必要としません。

450
jacobm

クラスThingを非静的な内部クラスとして宣言しました。それはそれがHelloクラスのインスタンスと関連付けられなければならないことを意味します。

あなたのコードでは、静的コンテキストからThingのインスタンスを作成しようとしています。それがコンパイラが不平を言っていることです。

いくつかの解決策があります。どのソリューションを使用するかは、達成したいことによって異なります。

  • ThingHelloクラスから移動します。

  • Thingstaticネストクラスに変更します。

    static class Thing
    
  • Helloのインスタンスを作成する前に、Thingのインスタンスを作成します。

    public static void main(String[] args)
    {
        Hello h = new Hello();
        Thing thing1 = h.new Thing(); // hope this syntax is right, typing on the fly :P
    }
    

意味のあるThingのインスタンスがHelloのインスタンスに依存している場合、最後の解決策(non-staticネストクラス)は必須です。たとえば、次のようになります。

public class Hello {
    public int enormous;

    public Hello(int n) {
        enormous = n;
    }

    public class Thing {
        public int size;

        public Thing(int m) {
            if (m > enormous)
                size = enormous;
            else
                size = m;
        }
    }
    ...
}

次のように、クラスThingのオブジェクトを作成しようとする生の試み

Thing t = new Thing(31);

それに対して31をテストするための明白なenormous値がないので、問題があるでしょう。このh.enormous値を提供するには、h外部クラスのインスタンスHelloが必要です。

...
Hello h = new Hello(30);
...
Thing t = h.new Thing(31);
...

ThingがなければHelloを意味しないからです。

入れ子/内部クラスの詳細については、 入れ子クラス(The Java Tutorials)

84
helloworld922

うーん...とても良い答えがたくさんありますが、もっと追加したいと思います。 Java-Javaの内部クラスを簡単に見れば、クラスを別のクラス内に定義することができます。このようにクラスを入れ子にできることには、いくつかの利点があります。

  1. 他のクラスのクラスをhide(カプセル化を強化)することができます - そのクラスがそのクラスに含まれるクラスによってのみ使用されている場合は特に重要です。この場合、外の世界がそれについて知る必要はありません。

  2. クラスは必要に応じて論理的にグループ化されているため、コードを保守しやすいにすることができます。

  3. 内部クラスは、それを含むクラスのインスタンス変数とメソッドへのaccessを持ちます。

主に3種類のInner Classes

  1. ローカルインナー
  2. 静的内部クラス
  3. 匿名内部クラス

覚えておくべき重要な点のいくつか

  • それが存在するLocal Inner Classにアクセスするためのクラスオブジェクトが必要です。
  • 静的内部クラスは、それが存在する同じクラスの他の静的メソッドと同じように直接アクセスされます。
  • 匿名内部クラスは、それが存在する同じクラスの他のメソッドやクラスと同様に、外部の世界には見えず、宣言されている場所で使用されます。

上記の概念を実際に見てみましょう。

public class MyInnerClass {

public static void main(String args[]) throws InterruptedException {
    // direct access to inner class method
    new MyInnerClass.StaticInnerClass().staticInnerClassMethod();

    // static inner class reference object
    StaticInnerClass staticInnerclass = new StaticInnerClass();
    staticInnerclass.staticInnerClassMethod();

    // access local inner class
    LocalInnerClass localInnerClass = new MyInnerClass().new LocalInnerClass();
    localInnerClass.localInnerClassMethod();

    /*
     * Pay attention to the opening curly braces and the fact that there's a
     * semicolon at the very end, once the anonymous class is created:
     */
    /*
     AnonymousClass anonymousClass = new AnonymousClass() {
         // your code goes here...

     };*/
 }

// static inner class
static class StaticInnerClass {
    public void staticInnerClassMethod() {
        System.out.println("Hay... from Static Inner class!");
    }
}

// local inner class
class LocalInnerClass {
    public void localInnerClassMethod() {
        System.out.println("Hay... from local Inner class!");
    }
 }

}

これが皆さんに役立つことを願っています。詳しくは を参照してください

24
Rupesh Yadav

次の簡単な例でそれを理解しましょう。これはNON-STATIC INNER CLASSであるために起こります。あなたは外のクラスのインスタンスが必要です。

 public class PQ {

    public static void main(String[] args) {

        // create dog object here
        Dog dog = new PQ().new Dog();
        //OR
        PQ pq = new PQ();
        Dog dog1 = pq.new Dog();
    }

    abstract class Animal {
        abstract void checkup();
    }

    class Dog extends Animal {
        @Override
        void checkup() {
            System.out.println("Dog checkup");

        }
    }

    class Cat extends Animal {
        @Override
        void checkup() {
            System.out.println("Cat Checkup");

        }
    }
}
10
AZ_

Thing内部クラス で、Helloのインスタンスに自動的に接続します。アタッチするHelloのインスタンスがないため、コンパイルエラーが発生します。無関係な 静的ネストクラス に変更することで、最も簡単に修正できます。

static class Thing
9
David Harkness