Ошибка недостижимого оператора при использовании цикла 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 и затем правильно скомпилируйте код без каких-либо других изменений в тексте программы.

Другие вопросы по тегам