10

static フィールドは、定義または初期化する前に参照することはできません。

static Integer j = i; /* compile error */
static final Integer i = 5;

ただし、インスタンスの初期化ブロック (匿名の内部クラス内) から参照された場合は、警告も生成されません。

例を参照してください:

class StaticInitialization {

    static final Object o = new Object() {{
        j = i;
    }};

    static Integer j, k;
    static final Integer i = 5;

    static final Object o2 = new Object() {{
        k = i;
    }};
}

結果はj == null,k == 5です。つまり、参照を作成したことは明らかであり、順序が重要であり、警告やコンパイル エラーはありません。

このコードは合法ですか?

4

6 に答える 6

1

最初のブロックでは、静的フィールドを初期化する前に参照しているのではなく、定義する前に参照しています (コンパイラが教えてくれるように)。これは機能します。たとえば、次のようになります。

static Integer j;
static final Integer i = j;

明示的に設定されていない場合、すべてのフィールドにはデフォルト値があります (オブジェクトの場合はnull参照、プリミティブの場合は対応する適切なデフォルト、0falseなど)。したがって、フィールドは常に初期化されるため、コンパイラはそれをチェックする必要はありません。

に関してfinal:それは実際には開発者の利益のために使用される修飾子です。JSLが述べているように、finalフィールドはアクセスする前に「確実に割り当てられる」必要があります。それ以外の場合は値がないという意味ではありません (そうでない場合final)、コンパイラがその割り当てを見つけることができない場合、明示的に割り当てないように保護することを意味します。

したがって、finalフィールド以外の場合は、明示的な割り当ての前にそれらを参照できます。上記のコード スニペットを貼り付けて確認してください。

于 2013-09-11T10:56:33.680 に答える
1

このコードは合法ですか? おそらく。静的変数を盗む際にオブジェクトのインスタンス化の意図的な副作用を分析するのは、コンパイラの仕事ではないと思います。

同じクラスの他の静的からの「参照前の宣言」の限定的な分析は、実際には、最も一般的なブーブーに対する単なるヘルパーであり、間接的なエラーに対する鉄壁の保証ではありません。

static「参照する前に宣言する」分析の範囲が、他の宣言の静的変数への直接アクセスに限定されていることに、まったく驚かない。これは、最小限の複雑さと非常に高速なシンプルでコンパクトな分析です。

オブジェクトのインスタンス化とメソッド呼び出しの副作用を考慮するように拡張すると、OTOH では、静的プログラム分析の 20 ~ 1000 倍の重みと範囲が必要になります。静的分析では、コンパイルされたプログラム コード全体にアクセスする必要があり、制約に基づいて何が起こるかを判断し、実行時間を数分で決定する必要があります。

これらの選択肢を考えると、Java 言語の設計者としては、同じクラス内のフィールドからの直接アクセスのみをカバーする単純な分析を選択するのはかなり簡単です。

于 2013-09-11T10:56:56.330 に答える
0

コードは次のようになります。

class StaticInitialization
{
    static final Foo1 o = new Foo1();
    static Integer j, k;
    static final Integer i = 5;
    static final Foo2 o = new Foo2();

    class Foo1
    {
        public Foo1()
        {
            j = i;
        }
    }

    class Foo2
    {
        public Foo2()
        {
            k = i;
        }
    }
}

iinsideを参照するとFoo1inull でした。ただし、内部で参照すると にiなります。がコンパイル定数 ( is not ) の場合、 5 になることに注意してください。5Foo2iiintIntegerj

この関連する質問を参照してください:静的​​な方法でオブジェクトを作成する

于 2013-09-11T11:01:04.637 に答える
0

はい、最初にすべての変数のスペースが割り当てられ (そして #0 で初期化され)、その後すべての初期化がコードの順序で行われるために発生します。

つまり、コードを次のように変更すると、次のようになります。

    クラス静的初期化 {

    static 整数 j、k;
    static final 整数 i = 5;

    static final Object o = new Object() {{
        j = i;
    }};

    static final Object o2 = new Object() {{
        k = 私;
    }};
    }

結果はすべてvariables == 5です。

于 2013-09-11T10:58:24.737 に答える
0

これはJLS 8.3.2.3で定義されています。

メンバーの宣言は、メンバーがインスタンスである場合にのみ、使用する前にテキストで表示する必要があります。

そのため、これを行うとエラーが発生します..

static Integer j = i; /* compile error */
static final Integer i = 5;

ただし、メソッドによるアクセスは同じようにはチェックされません。

于 2013-09-11T11:09:26.100 に答える