1. ホーム
  2. java

初期化されていないローカル変数で静的コンテンツにアクセスできないのはなぜですか?

2023-09-21 05:07:06

質問

以下のコードを見てください。

class Foo{
    public static int x = 1;
}

class Bar{    
    public static void main(String[] args) {
        Foo foo;
        System.out.println(foo.x); // Error: Variable 'foo' might not have been initialized
    }
}

静的フィールド x を経由して 未初期化の ローカル変数 Foo foo; コード foo.x はコンパイルエラーを発生させます。 Variable 'foo' might not have been initialized .

それは 見える このエラーは理にかなっているように見えますが、これは static メンバにアクセスするために、JVMは実際には を使用します。 その のみで、その変数の .

例えば foo を値 null にアクセスできるようになります。 x に問題なくアクセスできるようになります。

Foo foo = null;
System.out.println(foo.x); //compiles and at runtime prints 1!!! 

このようなシナリオがうまくいくのは、コンパイラが x が静的であることを認識し foo.x のように書かれたものとして扱います。 Foo.x (のように書かれているように見えます(少なくとも私は今までそう思っていました)。

ではなぜコンパイラは突然 foo という値を持つ を使うことはありません。 を全く使わないのですか?


免責事項: これは実際のアプリケーションで使用されるコードではありませんが、私はStack Overflowで答えを見つけることができなかったので、私はそれについて尋ねることにした興味深い現象です。

どのように解決するのですか?

§15.11. フィールドアクセス式 :

もしフィールドが 静的 :

一次式が評価され、その結果は破棄されます。 . もし一次式の評価が突然終了した場合、フィールドアクセス式も同じ理由で突然終了します。

先ほどは、フィールドアクセスは Primary.Identifier .

このことから、一見すると Primary を使用していないように見えても、評価され、その結果は破棄されるため、初期化が必要であることがわかります。 これは、引用文にあるように、評価によってアクセスが停止した場合に違いが生じる可能性があります。

EDITです。

この例では、視覚的な例として Primary が評価され、その結果が破棄されることを示す短い例です。

class Foo {
    public static int x = 1;
    
    public static Foo dummyFoo() throws InterruptedException {
        Thread.sleep(5000);
        return null;
    }
    
    public static void main(String[] args) throws InterruptedException {
        System.out.println(dummyFoo().x);
        System.out.println(Foo.x);
    }
}

ここでは dummyFoo() はまだ評価されています。 print は5秒間の Thread.sleep() を返すにもかかわらず、常に null の値を返しますが、これは破棄されます。

式が評価されなかった場合 print が即座に現れますが、これはクラス Foo を直接使って xFoo.x .

注意 メソッド呼び出しもまた Primary で示される §15.8 一次式 .