Подтвердить что ты не робот

Почему компилятор Java не создает недопустимую ошибку оператора для недостижимого оператора?

Если я попытаюсь скомпилировать

for(;;)
{

}
System.out.println("End");

В компиляторе Java появляется сообщение об ошибке Unreachable statement. Но если я добавлю еще один "недостижимый" (по мне) оператор break и сделаю это:

for(;;)
{
    if(false) break;
}
System.out.println("End");

Он компилируется. Почему это не приводит к ошибке? Является ли Java попыткой сказать, что Две ошибки сделать сделать правильно?

4b9b3361

Ответ 1

Поведение определено в описании JLS недостижимых утверждений:

Оператор then доступен, если утверждение if-then доступно.

Итак, компилятор определяет, что оператор then (break;) доступен, независимо от условия в if.

И немного дальше, мой удар:

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

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

Таким образом, for может завершиться нормально, потому что then-statement содержит a break. Как вы заметили, это не сработает, если вы замените break на return.


Объяснение объясняется в конце раздела. По существу, if имеет специальную обработку, позволяющую конструкции, такие как:

if(DEBUG) { ... }

где DEBUG может быть константой времени компиляции.

Ответ 2

Как объяснено в моем ответе на аналогичный вопрос, конкретный конструктор if(compile-time-false) освобождается от правил недостижимости как явный бэкдор. В этом случае компилятор рассматривает ваш break как достижимый из-за этого.

Ответ 3

Из JLS

Операция if-then может завершиться нормально, если хотя бы один из верно следующее:

Оператор if-then доступен и выражение условия не является постоянное выражение, значение которого истинно.

> Оператор then может завершиться нормально.

Значит if(false).

Эта способность "условно компилировать" оказывает значительное влияние, и отношение к бинарной совместимости. Если набор классов которые используют такую ​​переменную "флаг", компилируются, а условный код пропущено, позже не будет достаточно распространять только новую версию класс или интерфейс, который содержит определение флага. изменение значения флага, следовательно, не совместимо с бинарными с уже существующими двоичными файлами. (Есть и другие причины для такая несовместимость, как, например, использование констант в случае метки в операторах switch;)

Ответ 4

В принципе, недостижимый код обнаруживается путем анализа программы статически без, фактически выполняющей код. Пока условие будет проверено во время выполнения. Таким образом, когда этот анализ имеет место, он фактически не смотрит в состояние, а просто проверяет, что break; доступен (доступен) через if.

Ответ 5

Основная причина, по которой Java не обнаруживает все недостижимые утверждения, состоит в том, что вообще невозможно ответить, доступен ли код или нет. Это следует из того факта, что проблема с остановкой неразрешима над машинами Тьюринга.

Итак, ясно, что все недостижимые утверждения не могут быть обнаружены, но почему бы не попробовать оценить условия? Представьте себе, что используемое условие не просто false, а нечто вроде ~x == x. Например, все эти операторы будут печатать true для каждого int x (источника).

    System.out.println((x + x & 1) == 0);
    System.out.println((x + -x & 1) == 0);
    System.out.println((-x & 1) == (x & 1));
    System.out.println(((-x ^ x) & 1) == 0);
    System.out.println((x * 0x80 & 0x56) == 0);
    System.out.println((x << 1 ^ 0x1765) != 0);

Операции могут быть довольно сложными; для их решения требуется время. Это значительно увеличит время сборки, и в конце концов, оно не обнаружит все недостижимые утверждения. Компилятор был разработан, чтобы приложить некоторые усилия, но не тратить слишком много времени на это.

Остается только вопрос: где прекратить разрешать условия? Причины этого не имеют математического обоснования и основаны на сценарии использования. Обоснование для вашего конкретного случая дается JLS-14.21