Ошибка недостижимого оператора при использовании цикла while в Java
Возможный дубликат:
Почему этот код выдает ошибку "Недоступное заявление"?
Это кажется очень простым вопросом, я нашел этот вопрос в одной книге. Если кто-нибудь поможет мне выяснить, почему я получаю ошибку.
do {
System.out.print("inside do");
} while (false);
while (false) { // error
System.out.print("inside while");
}
System.out.print("outside");
Я думал, и, по моему мнению, выход должен быть внутри dooutside. Но он показывает ошибку компилятора: недостижимое утверждение. Затем я попытался выяснить, почему он показывает ошибку компиляции: недостижимое утверждение *. Итак, я изменяю приведенный выше код, как это
boolean i = false;
do {
System.out.print("inside do");
} while (false);
while (i) { // ok
System.out.print("inside while");
}
System.out.print("outside");
Теперь он показывает ожидаемый результат, то есть внутри dooutside. Итак, мой вопрос - что имеет значение в первом и втором случае? Кроме того, когда я проверяю
if(false){
//something here
}
Затем приведенный выше код выполняется без ошибок.
2 ответа
Основное различие между первыми двумя примерами заключается в том, что в первом случае условие является константой, а во втором - нет.
Например, если вы измените boolean i = false;
в final boolean i = false;
, вы получите ту же ошибку компиляции, потому что теперь я константа.
Правила для недостижимых операторов определены в JLS 14.21. В частности, существует специальный режим лечения if
позволять if(DEBUG)
структуры, где DEBUG
может быть константой.
Для do / while
, оператор внутри будет выполнен один раз, поэтому проблем нет.
Подробнее о константах в этом посте.
Компилятор выдает ошибку " Недостижимый оператор", потому что ваш System.out.print("inside while");
код никогда не может быть достигнут с
while (false) { // error
System.out.print("inside while");
}
Компилятор знает, что while (false)
никогда не будет правдой и предупреждает вас (с ошибкой) о мертвом коде.
Напротив, если вы поместите переменную в while
вместо этого, поскольку природа переменных заключается в том, что они могут изменяться (изменяться), статический анализ компилятора не идентифицирует недоступный код. (Даже во многих ситуациях, когда вы или я могли бы взглянуть на это и сказать "этот код никогда не будет запущен"; анализ компилятора довольно поверхностный, это не его основная задача. Существуют более сложные инструменты анализа и покрытия кода, которые вы можете использовать.)
В отношении if (false)
вот что JLS должен сказать об этом:
Например, следующий оператор приводит к ошибке времени компиляции:
while (false) { x=3; }
потому что утверждение
x=3
; не достижимо; но внешне похожий случай:
if (false) { x=3; }
не приводит к ошибке времени компиляции. Оптимизирующий компилятор может понять, что утверждение
x=3;
никогда не будет выполнен и может пропустить код для этого оператора из сгенерированного файла класса, но операторx=3;
не считается "недоступным" в техническом смысле, указанном здесь.Обоснование этого отличающегося подхода состоит в том, чтобы позволить программистам определять "переменные флага", такие как:
static final boolean DEBUG = false;
а затем написать код, такой как:
if (DEBUG) { x=3; }
Идея состоит в том, что должно быть возможно изменить значение
DEBUG
от false до true или от true до false и затем правильно скомпилируйте код без каких-либо других изменений в тексте программы.