20

重複の可能性:
Java が内部クラスの静的フィールドを禁止するのはなぜですか?

私は仕様を調べていて、最終コンパイル時定数ではない内部クラスに static メンバーを持つことはできないことがわかりました。

class HasStatic {
    static int j = 100;
}
class myInnerClassTest {
    class Inner extends HasStatic {
        static final int x = 3;  // OK: compile-time constant
        static int y = 4;  // Compile-time error: an inner class
    }
    static class NestedButNotInner{
        static int z = 5;    // OK: not an inner class
    }
    interface NeverInner {}   // Interfaces are never inner
}

一方、静的な最終メンバーを使用できるのに、内部クラスに静的メソッドを使用できないのはなぜですか? 所有者クラスから静的メンバーを継承できること。しかし、なぜそうすべきではないのですか?それが痛いOOPのプリンシパルは何ですか?

4

5 に答える 5

12

クラスmyInnerClassTestが static として宣言されていません。では、静的フィールドを持つことは正確には何を意味するのでしょうか?

でしょうか

  • 囲んでいるインスタンスが何であれ、すべてのインスタンスで同じですか?
  • 同じ囲みインスタンスを持つこの内部クラスのすべてのインスタンスで同じですか?

一見したところ、ほとんどのプログラマーはおそらく最初のケースだと思うでしょうが、(非静的) 内部クラスのカプセル化ロジックはおそらく 2 番目の選択肢につながるはずです。どちらの場合 (または両方とも異なる修飾子を使用する場合) でも、staticおそらく必要とは見なされていなかった新しい定義が必要になります。どちらの場合も、プログラマーは正確な意味について混乱するでしょう。

仕様から:

内部クラスは、明示的または暗黙的に静的に宣言されていないネストされたクラスです。

内部クラスには、ローカル (§14.3)、匿名 (§15.9.5)、および非静的メンバー クラス (§8.5) が含まれます。

内部クラスは、静的初期化子 (§8.7) またはメンバー インターフェイスを宣言しない場合があります。そうしないと、コンパイル時エラーが発生します。

内部クラスは、定数変数 (§4.12.4) でない限り、またはコンパイル時エラーが発生しない限り、静的メンバーを宣言できません。

于 2012-10-04T12:34:39.933 に答える
10

JLSによると:-

8.1.3内部クラスとそれを囲むインスタンス

内部クラスは、明示的または暗黙的に静的として宣言されていないネストされたクラスです。内部クラスは静的初期化子(§8.7)またはメンバーインターフェースを宣言できません。内部クラスは、コンパイル時定数フィールド(§15.28)でない限り、静的メンバーを宣言できません。

内部クラスで使用されているが宣言されていないローカル変数、仮メソッドパラメータ、または例外ハンドラパラメータは、finalとして宣言する必要があります。内部クラスで使用されているが宣言されていないローカル変数は、内部クラスの本体の前に確実に割り当てる必要があります(§16)。

私が重要だと思ったこれらの2つのこととは別に、そこからそれを得ることができるものはもっとたくさんあります。、、、および..についての膨大な説明がありinner classesます。anonymous inner classesnested classes

更新された説明:-

考えてみてください。静的ブロックはクラスの初期化中に実行され、それを囲むクラスのインスタンスがないと、非静的内部クラスを初期化できません。これが理由です。

内部クラスは、囲んでいるクラスのに関連付けられています。それらは、囲んでいるクラスの他のインスタンス属性のようです。現在、コンテキストにフィールドinstanceを埋め込むことは意味がありません。ただし、コンパイル時として宣言した場合それらが許可される定数。staticnon-static

:-static final Object = null コンパイル時定数ではありません..したがって、内部クラス内にそれらを含めることはできません

一方、内部クラスstaticが実際にはネストされたクラスである場合、フィールドは静的に宣言できます。これは、クラスに関連付けられたままなので、インスタンス化されたクラスを囲む前でもアクセスできます。

私はそれが理にかなっていることを願っています。

更新2:-

public class A {
   class B {
        static int x = 0;
   }
}

上記のコードでstatic variable xは、はクラスBのすべてのインスタンスに共通です。また、の各インスタンスにはclass A独自のコピーがありますclass BJVMはが作成されるたびにクラスBをロードする必要があるためinstance of A)。

したがって、コンパイル時定数でない限り、static variable xのすべてのインスタンス間で共有することはできませんでし。クラスAの各インスタンス。したがって、クラスAのインスタンスごとに異なります。したがって、静的変数は、クラスAの異なるインスタンス間で実際には共有されません。静的変数には意味がありません。)class AB.xB.xx

私は今、それが理にかなっていることを願っています。

于 2012-10-04T12:38:19.010 に答える
1

すべての制限は JLS #8.1.3 に記載されています。内部クラスとそれを囲むインスタンス

静的宣言はクラスに関連付けられているため、内部クラス内で宣言すると、クラスではなくインスタンスに関連付けられます。

内部クラス

非静的内部クラスは Object のメンバーです。また、メンバーの初期化は、オブジェクトのインスタンスが作成されたときにのみ発生します。静的変数が許可されている場合、インスタンスの作成前に初期化が行われます。

そのため、個別non-staticstatic内部クラスがあります。

内部クラスにアクセスするには、常に外部クラスのインスタンスが必要です。Outer.Inner例外はstatic inner class、非静的内部クラスに適用できる制約がない場合です。

static class Inner {
    static final int x = 3; // OK: compile-time constant
    static int y = 4;// OK
    static class NestedButNotInner {// OK

    }

    interface NeverInner {// OK
    };
}

ただし、定数は許可されており、JLS で文書化されています。

于 2012-10-04T12:37:39.627 に答える
0

内部クラスは最上位クラスに密接に関連付けられているため、内部ビアを作成するには外部クラスのインスタンスが必要です。

Outer o = new Outer();
Inner i = o.new Inner();

したがって、これはクラスではなくインスタンスに関連付けられます。

于 2012-10-04T12:51:19.807 に答える
-1

ご存知のように、内部クラスは所有者クラスから static メンバーを継承できます。

class HasStatic {
    static int j = 100;
}
class myInnerClassTest {
    class Inner extends HasStatic {
    }      
    public static void main(String[] args){
        System.out.println(Inner.j);
    }
}

そして、「100」と出力します。

于 2012-10-04T12:55:19.237 に答える