0

この単純な Java コードを見てください。

class A {
    public static void main(String[] args) {
        final int x;
        try {
            throw new RuntimeException();
            x = 1;
        } finally {}
        x = 2;
        System.out.println("x: " + x);
    }
}

「x:2」と出力されると思います。

A.java:6: unreachable statement
            x = 1;
            ^
A.java:8: variable x might already have been assigned
        x = 2;
        ^
2 errors

8行目で最終変数を再割り当てx = 2する可能性があるため、コンパイルできないと言われていますが、上記のように、行に到達できないため、再割り当てではなく初めて割り当てられるため、これは誤りです。x = 1

コンパイラは、x が割り当てられていないことがわかっているのに、「x は既に割り当てられている可能性があります」というエラーを出すのはなぜxですか?

4

6 に答える 6

2

JLSの第16章で説明されています

[...] 同様に、すべての空白の final 変数は、多くても 1 回代入する必要があります。割り当てが発生したときは、確実に割り当てを解除する必要があります。

このような代入は、変数の単純名(またはフィールドの場合は、これによって修飾された単純名) が代入演算子の左側にある場合にのみ発生するように定義されています。

空白の最終変数への代入ごとに、代入の前に変数の代入を確実に解除する必要があります。そうしないと、コンパイル時エラーが発生します。

そのため、JLS は到達不能なコードを気にしていないようです。

例外に関しては、次のように述べています。

catch 句 (§14.20) の例外パラメーター V は、catch 句の本体の前に確実に割り当てられます (さらに、確実に割り当て解除されません)。

ここでの問題は、x=1x=2の両方が間違いなく次のように割り当てられていることです。

try ステートメントに finally ブロックがある場合は、次の規則も適用されます。

V is definitely assigned after the try statement iff at least one of the following is true:

    V is definitely assigned after the try block and V is definitely assigned after every catch block in the try statement.

    V is definitely assigned after the finally block.

    V is definitely unassigned after a try statement iff V is definitely unassigned after the finally block.
于 2013-06-30T23:38:54.900 に答える
0

おそらく言語定義の問題です。仕様の 1 つの領域は、既に割り当てられている可能性がある場合、再割り当てを禁止しています。別の領域では、到達不能コードについて説明しています。

この 2 つの組み合わせは、おそらく実際に扱われることはありません。

あなたが本当に達成しようとしていることをもう少し代表するものを提供してもらえますか?

于 2013-06-30T23:34:08.053 に答える
0

Javaを学んでいるようです。最初のエラーは、例外をスローした後にブロックの実行を続行できないことをコンパイラが認識できるためです。制御は、例外がキャッチされた場所にジャンプします。他のポスターは、2 番目のエラーを説明しています。

于 2013-07-01T00:05:11.063 に答える
0

次のような、それほど単純ではない他のケースを見てきました。

final int x;
boolean b = ...;
if(b) {
   x = 1;
}
...
if(!b) {
   x = 2;
}

最も簡単な解決策は、一時的な非 final 変数に割り当ててから、それを final 変数にコピーすることです。

final int x;
int _x = 0;
boolean b = ...;
if(b) {
   _x = 1;
}
...
if(!b) {
   _x = 2;
}
x = _x;
于 2013-07-01T00:05:29.643 に答える
0

最初のエラーは、到達不能コードの結果です。例外をスローすると、メソッドは停止し、次の行は実行できなくなります。x から final 修飾子を削除するだけで、2 番目のエラーを修正できます。しかし、なぜあなたは RuntimeException をスローすることだけを目的としたプログラムを書いているのでしょうか?

于 2013-06-30T23:30:08.503 に答える
0

Java コンパイラは、人間と同じように物事を見ることができません。原因と結果は見えず、何が間違っているかだけが見えます。この場合、エラーの 1 つを修正しても、もう 1 つのエラーが持続するため、これは良いことかもしれません。

于 2013-06-30T23:32:28.110 に答える