54
class Foo{
    public static void main(String args[]){
        final int x=101;

        int y;
        if(x>100){
            y=-1;
        }
        System.out.println(y);
    }
}

Javaコンパイラは、ifステートメントの条件を常に真であると理解しているため、yは常に初期化されます。予想どおり、コンパイルエラーはありません。

class Bar{
    public static void main(String args[]){
        final int x;
        x=101;

        int y;      
        if(x>100){
            y=-1;
        }
        System.out.println(y);
    }
}

しかし、xの宣言と初期化を2行に分割すると、コンパイラは条件が常にtrueであり、yが常に初期化されることを認識していないようです。

final int x;
x=101;
byte b;
b=x;
System.out.println(b);

ここでも同じことが起こり、コンパイラは精度の低下エラーを出します。

final int x=101;
byte b;
b=x;
System.out.println(b);

この場合も、コンパイラーはxがbの範囲内にあることを理解できます。

4

3 に答える 3

46

移植性を目指す一環として、コンパイラーが何を受け入れ、何を拒否するかについて、非常に具体的な一連のルールがあります。これらのルールは、変数がその使用時に確実に割り当てられているかどうかを判断するときに、限られた形式のフロー分析のみを許可および要求します。

Java言語仕様の第16章を参照してください。明確な割り当て

重要なルールは16.2.7のものです。ifステートメント、「if(e)S」の場合。確実に割り当てられるためのルールは、次のように拡張されます。

Vif(e)Sの後に割り当てられ 、VはSの後に割り当てられ、Vはeの後に割り当てられます。

yは関連するVです。ifステートメントの前に割り当てが解除されます。実際、S、y = {y = -1;}の後に割り当てられますが、x>100がfalseの場合は割り当てられません。

したがって、yはifステートメントの後に明確に割り当てられません。

より完全なフロー分析では、条件x> 100が常に真であると判断されますが、JLSは、これらの特定のルールに基づいてプログラムを拒否するようにコンパイラーを要求します。

最後の変数は問題ありません。ルールは実際には:-

「最後の変数が割り当てられた場合、割り当ての直前に確実に割り当てが解除されていない限り(§16)、コンパイル時エラーになります。」

宣言はそれを完全に割り当てられていないままにし、限られたフロー分析でさえ、xが割り当て時にまだ確実に割り当てられていないことを決定できます。

于 2012-11-05T15:56:18.207 に答える
27

これは、ステートメントが実行されるかどうかをコンパイラーがどのように決定するかと関係があります。JLS#16で定義されています:

各ローカル変数とすべての空白の最終フィールドには、その値へのアクセスが発生したときに、確実に割り当てられた値が必要です。

yあなたの場合、コンパイラはそれが確実に割り当てられていると判断できず、エラーが発生します。これは、条件が常に真であると判断する必要があるためです。これは、の条件が定数式である場合にのみif可能です

JLS#15.28定数式を定義しています:

コンパイル時定数式は、プリミティブ型の値または突然完了しない文字列を示す式であり、以下のみを使用して構成されます。

  • [...]
  • 定数変数(§4.12.4)を参照する単純な名前(§6.5.6.1)。

JLS#4.12.4は、定数変数を次のように定義しています。

プリミティブ型または文字列型の変数は、最終的にコンパイル時の定数式で初期化され、定数変数と呼ばれます。

あなたの場合、final int x = 101;は定数変数ですが、そうでfinal int x; x = 101;はありません。

于 2012-11-05T15:57:53.277 に答える
11

x2番目のコードの変数に対して行ったことは、空白の最終変数と呼ばれます。最終変数が宣言されたときに初期化されていない場合、それは空白の最終変数と呼ばれます。

多くのJava開発者は、最終変数の値はコンパイル時にわかっていると考えています。これは常に正しいとは限りません。コンパイル時に不明な空白の最終変数の値と言われています。したがって、2番目のコードではコンパイルエラーが発生します。コンパイラは、最終変数が初期化されたことを認識できますがx、コンパイルはその値を認識しません。したがって、コンパイラはifステートメントを解決できません。そのため、変数yは初期化されていないと考えます。

Javaの最終変数について詳しくは、こちらをご覧ください。

于 2012-11-05T16:13:24.900 に答える