3

次の形式のコードがあります。

class Test {
  private final A t;

  public Test() {

    for ( ... : ... ) {
      final A u = null;
    }

    t = new A();
  }

  private class A {}
}

コンパイラは次のように述べています。

variable t might already have been assigned

興味深いことに、ループに次の変更を加えるとうまくいきます!

  • ループの内容を次のように変更しますA u = null
  • ループを削除します (ただし、保持しますfinal A u = null;)
  • foreach スタイルのループを従来のカウント ループに置き換える

ここで何が起こっているのですか?

注:エラーを引き起こす最小限の例を取得できなかったため、「環境」(約1400 loc)に問題がある可能性があります。tただし、t他のどこにも書かれていないように、の初期化を妨げる可能性のあるものはわかりません。

楽しい事実: IntelliJ IDEA は、「変数 'u' は 'final' 修飾子を持つことができます...」と表示します。

javac 1.6.0_26 を使用しています。

更新:ほら、この例はとても最小限です:

import java.util.List;

class A {
  private final boolean a;

  public A() {
    for ( final Object o : new Object[] {} ) {
      final Object sh = null;
    }

    a = true;
  }

  class B {
    private final Object b1;
    private final Object b2;

    B() {
      b1 = null;
      b2 = null;
    }
  }
}

でのコンパイルに失敗しますがjavac 1.6.0_26、でコンパイルされjavac 1.7.0_02ます。それで、私はいくつかの邪悪なコーナーケースに遭遇したと思います...何か?

のいずれかを実行できることに注意してください。

  • いずれかのメンバーを削除する
  • finalループ内を削除A()
  • forループを通常のループに置き換えます。for ( int i=0; i<100; i++ ) { ... }

そしてそれはコンパイルされます。

4

4 に答える 4

1

あなたがたくさんのコードを持っているなら、私はこれを試してみます。

private final A t;

public Test() {
    final int t = 1;

   for ( ... ) {
      final A u = null;
   }

   this.t = new A();

これにより、初期化tする可能性のあるコードが失敗する(そしてコンパイラに表示される)可能性があります。

于 2012-02-02T13:21:30.210 に答える
1

コンストラクターが、それ自体が設定されていない別のコンストラクターを呼び出したt場合、コンパイラーはそれを理解できません。

ここを参照してください。

于 2012-02-02T13:29:36.877 に答える
1

この問題は Java 7 で修正されているため、おそらく Java 6 コンパイラのバグです。

于 2012-02-06T10:36:42.167 に答える
-2

オブジェクトを final var に保存しても、オブジェクトが不変になるのではなく、その参照になることは私の理解です。これは、final キーワードを削除すると機能する理由を説明しており、for ループを削除すると、インスタンスではなくオブジェクト参照にアクセスしていると思います。

于 2012-02-02T13:36:46.057 に答える