Бесконечный цикл прерывает подпись метода без ошибки компиляции

Мне интересно, почему в Java допустим следующий код, не получив ошибку компиляции? На мой взгляд, этот код нарушает подпись метода, не возвращая ни одного String. Может ли кто-нибудь объяснить, что мне здесь не хватает?

public class Loop {

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

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

Ответ 1

Окончательный } метода недоступен - вы получаете только ошибку компиляции, если возможно дойти до конца метода, не возвращая значения.

Это более полезно для случаев, когда конец метода недоступен из-за исключения, например

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:

Оператор A while может завершиться нормально, если по крайней мере одно из следующего верно:

  • Оператор while доступен и выражение условия не является константным выражением (§15.28) со значением true.
  • Существует допустимый оператор break, который выходит из инструкции while.

В вашем случае выражение условия является константой со значением true и не существует каких-либо операторов break (достижимых или других), поэтому оператор while не может нормально функционировать.

Ответ 2

 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