web-dev-qa-db-ja.com

無限ループはコンパイルエラーなしでメソッドシグネチャを壊します

次のコードがコンパイルエラーなしでJavaで許可されるのはなぜですか?私の意見では、このコードはStringを返さないことで、メソッドのシグネチャを壊します。誰かが私がここで欠けているものを説明できますか?

public class Loop {

  private String withoutReturnStatement() {
    while(true) {}
  }

  public static void main(String[] a) {
    new Loop().withoutReturnStatement();
  }
}
65
Simo Martomaa

メソッドの最後の}に到達できません。値を返さずにメソッドの最後に到達できる場合にのみ、コンパイルエラーが発生します。

これは、例外が原因でメソッドの終わりに到達できない場合に、より便利です。

private String find(int minLength) {
    for (String string : strings) {
        if (string.length() >= minLength) {
            return string;
        }
    }
    throw new SomeExceptionIndicatingTheProblem("...");
}

このためのルールは JLSセクション8.4.7 にあります:

メソッドが戻り値の型を持つように宣言されている場合(§8.4.5)、メソッドの本体が正常に完了できる場合(§14.1)、コンパイル時エラーが発生します。

メソッドが正常に完了できないため、エラーは発生しません。重要なのは、正常に完了できないというだけでなく、仕様が正常に完了できないことを認識していることです。から JLS 14.21

whileステートメントは、次の少なくとも1つが当てはまる場合、正常に完了することができます。

  • whileステートメントは到達可能であり、条件式は値trueの定数式(§15.28)ではありません。
  • breakステートメントを終了する到達可能なwhileステートメントがあります。

あなたの場合、条件式値がtrueの定数であり、breakステートメントはありません。 (到達可能またはその他)したがって、whileステートメントは正常に完了できません。

83
Jon Skeet
 private String withoutReturnStatement() {
    while(true) {
        // you will never come out from this loop
     } // so there will be no return value needed
    // never reach here ===> compiler not expecting a return value
  }  

より明確にするためにこれを試してください

private String withoutReturnStatement() {
    while(true) {}
    return ""; // unreachable
}

unreachableステートメントと書かれています