質問1:
次のコードがreturnステートメントなしでコンパイルされるのはなぜですか?
public int a()
{
while(true);
}
これはJLS§8.4.7でカバーされています:
メソッドが戻り値の型を持つように宣言されている場合(§8.4.5)、メソッドの本体が正常に完了すると、コンパイル時エラーが発生します(§14.1)。
つまり、戻り値の型を持つメソッドは、値を返すreturnステートメントを使用することによってのみ戻る必要があります。このメソッドは、「本体の端をドロップオフする」ことはできません。メソッド本体のreturnステートメントに関する正確な規則については、§14.17を参照してください。
メソッドが戻り値の型を持ち、returnステートメントを含まない可能性があります。以下はその一例です。
class DizzyDean {
int pitch() { throw new RuntimeException("90 mph?!"); }
}
コンパイラーはループが終了しないことを知っているため(true
もちろん、常にtrueです)、関数が「正常に戻る」ことができない(本体の最後をドロップする)ことができないことを知っているため、がないことは問題ありませんreturn
。
質問2:
一方、次のコードがコンパイルされるのはなぜですか?
public int a()
{
while(0 == 0);
}
以下はそうではありませんが。
public int a(int b)
{
while(b == b);
}
この0 == 0
場合、コンパイラーはループが終了しないことを認識しています(0 == 0
常にtrueになります)。しかし、それについてはわかりませんb == b
。
何故なの?
コンパイラーは定数式(§15.28)を理解します。§15.2の 引用-式の形式(奇妙なことに、この文は§15.28にないため):
一部の式には、コンパイル時に決定できる値があります。これらは定数式です(§15.28)。
あなたのb == b
例では、変数が含まれているため、定数式ではなく、コンパイル時に決定されるように指定されていません。我々は(場合ものの、常にこのような場合には真であることが起こっていることを確認できb
たdouble
QBruteとして、指摘し、我々は簡単にだまされてはいけ可能性がDouble.NaN
ある、ない==
自体)が、JLS定数式はコンパイル時に決定されることのみを指定、それはコンパイラが非定数式を評価しようとすることを許可しません。bayou.io が理由を指摘しました。コンパイル時に変数を含む式を決定しようとする道を歩み始めたら、どこで停止しますか?b == b
明らかである(非、NaN
値)、しかしどうa + b == b + a
ですか?または(a + b) * 2 == a * 2 + b * 2
?定数で線を引くことは理にかなっています。
したがって、式を「決定」しないので、コンパイラーはループが終了しないことを知らないため、メソッドが正常に戻ることができると考えていますreturn
。これは、を使用する必要があるため、許可されていません。だからそれはの欠如について不平を言うreturn
。