5

引用JLS #8.1.3 :

内部クラスは静的初期化子を宣言しない場合があります( §8.7 )......

これは次のように示されます。

class A {
    class B {
        static { // Compile-time Error: Cannot define static initializer in inner type A.B
            System.out.println("Class is initializing...");
        }
    }
}

Java の内部 (非静的) クラスは、他のすべてのクラスと同じようにクラス ローダーによってロードされるため、静的初期化子を使用できないのはなぜでしょうか?

この制限の背後にある理由は何ですか?

4

3 に答える 3

0

Inner クラス自体が静的ではないためだと思います。Javaの観点からそれはインスタンス変数であり、私はそれを推測します(1)クラスローダは、潜在的な静的オブジェクトを見つけて初期化するために内部の非静的クラスにクロールするようには設計されていません。

しかし、それは不可能な問題ではありません。次の例を見てください。

public class Outer {
    public static class Inner {
        Outer owner;
        static String constant;

        {
            constant = "foo";
        }

        private Inner(Outer owner) {
            if (owner == null) {
                throw new NullPointerException();
            }
            this.owner = owner;
        }
    }

    public Inner newInner() {
        return new Inner(this);
    }
}

Innerstatic と宣言されているため、警告さえありません。

Outerしかし、よく見ると、これには外側のインスタンスへのポインターがありOuter、プライベート コンストラクターしかないため作成することしかできず、その所有者を null にすることはできません。プログラマーの観点からは、非静的内部クラスのすべての制約があり、( のような特別なイディオムを除いてOuter.this) 同じように使用できますが、コンパイラの観点からは静的であり、静的フィールドは正しくなります。最初のOuterクラスの初期化で初期化されます。

(1) : Pacerier は、これが正しくない理由を以下のコメントで説明しています。

于 2014-08-23T08:29:50.657 に答える
-1

定義には矛盾があります。

JLS §8.1.3から:

最も内側のメソッド、コンストラクター、インスタンス初期化子、静的初期化子、フィールド初期化子、またはステートメントまたは式を囲む明示的なコンストラクター呼び出しステートメントが静的メソッド、静的初期化子、変数初期化子である場合にのみ、ステートメントまたは式は静的コンテキストで発生します。静的変数の、または明示的なコンストラクター呼び出しステートメント (§8.8.7)。

...

内部クラス (宣言が静的コンテキストで発生しない) が、字句的に囲んでいるクラスのメンバーであるインスタンス変数を参照する場合、対応する字句的に囲んでいるインスタンスの変数が使用されます。

于 2014-08-23T05:13:42.207 に答える