私はここで質問を読んでいた:Javaの:どのような順序でのstatic finalフィールドが初期化されていますか?
答えによると、
「値コンパイル時定数が最初に初期化されているインタフェースの最後のクラス変数やフィールドを除いて...」
私は次のように失敗するので、これは正しくないと思います。
static {
String y = x;
}
public static final String x = "test";
静的ブロックでは、x
認識されていません。その答えが正しいかどうか誰もがコメントを喜ばせることはできますか?
以下のための初期化は、 JLSは、彼らが様々なケースで宣言されている前に、変数を参照することはできませんという事実は変わりません。これはで説明されてJLS§8.3.3:
宣言の使用後にテキストで表示され、クラス変数の使用は、時にはこれらのクラス変数がスコープ(§6.3)であるにも関わらず、制限されています。具体的には、次のすべてに該当する場合、コンパイル時のエラーは、次のとおりです。
クラスまたはCインタフェースクラス変数の宣言は、クラス変数の使用後にテキストで表示されます。
使用は、Cのクラス変数初期化子又はCの静的初期化子のいずれかで単純な名前です。
使用は、割り当ての左側にありません。
Cは、使用を囲む最も内側のクラスまたはインタフェースです。
あなたのコードは、このコンパイルerorrを取得する理由です。
エラー:違法前方参照
最初に初期化されている一定の変数であり、静的フィールドが実際に定義されていることを声明JLS§12.4.2:
それ以外の場合は、Cのクラスオブジェクトの初期化が現在のスレッドによって進行中であるという事実を記録し、LCを解放します。
その後、一定の変数であるCの静的フィールドを初期化(§4.12.4、§8.3.2、§9.3.1)。
...
- それらは単一のブロックであるかのように、次は、テキストの順序で、クラス変数初期化子及びクラスの静的初期化子、またはインタフェースのフィールド初期化子のいずれかを実行します。
あなたが見ることができるように、一定の変数はステップ9でステップ6が、他に初期化されます。
これは、動作を示しています。
public class Example {
static String y;
static {
y = foo();
}
static String foo() {
return x.toUpperCase();
}
public static final String x = "test";
public static void main(String[] args) throws Exception {
System.out.println(x);
System.out.println(y);
}
}
コンパイルし、出力します。
テスト TEST
contastで、あなたが変更した場合x
、それはもはや一定ではないので、行を:
public static final String x = Math.random() < 0.5 ? "test" : "ing";
これはコンパイルが、あるため、その後失敗しx
ているnull
のとy = foo();
。
誤解を避けるために:私はしません。そのようなフィールドを初期化する方法を使用することをお勧めします。:-)