Когда в Java возникает условие "недостижимый код"?


Когда после бесконечного цикла записывается какое-либо утверждение, это утверждение становится недостижимым кодом. Например:

for(;;) 
{
}
Sytem.out.println("Test-1"); //unreachable code
Но здесь я столкнулся с некоторыми трудностями.

Посмотрите на два фрагмента кода ниже:

Фрагмент кода 1:

for(final int z=4;z<6;)
{
}
System.out.println("Test-2"); //unreachable code

Здесь последнее утверждение должно быть недостижимым, потому что цикл бесконечен, а результат соответствует ожидаемому.

Фрагмент Кода 2:

final int z=4;
for(;;)
{
    if(z<2)
        break;
}
System.out.println("Test-3");  //not unreachable

Концептуально цикл for В приведенном выше коде также бесконечен, поскольку z является конечным и if(z<2) определяется только во время компиляции.Условие if никогда не будет истинным, и цикл никогда не разорвется. Но последнее утверждение в приведенном выше коде не является недостижимым.

Вопросы:

  1. Почему это происходит ?

  2. Может ли кто-нибудь сказать мне точные правила, по которым мы можем увидеть, является ли код недостижимым или нет.

3 5

3 ответа:

Ключевая фраза в http://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.21 это:

Это ошибка времени компиляции, если оператор не может быть выполнен, потому что она недостижима.

Этот раздел посвящен точному объяснению слова "достижимый.- Идея в том, что должна быть какая-то возможная казнь . путь от начала конструктора, метода, экземпляра инициализатор, или статический инициализатор, содержащий инструкцию to то само утверждение. При анализе учитывается структура заявления. за исключением особого режима while, do и для высказывания, выражение условия которых имеет постоянное значение true, то значения выражений не учитываются при анализе потока.

Следовательно, компилятор не вычисляет z<2 в вашей инструкции if() и не знает что он никогда не оценит до true.

Это определяет недостижимый код, поскольку Java spec обеспокоен. Важно, чтобы компиляторы придерживались спецификации, потому что изменение правил может привести к тому, что код, который использовался для компиляции, не будет компилироваться.

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

Если я наберу следующий код в Eclipse:

final int x = 0;
if(x == 1) {
    System.out.println("This never happens");
}

... Я получаю предупреждение "мертвый код". Компилятор знает, что код не может быть достигнут , но он не может отказаться от компиляции, потому что код формально не является " недостижимым" согласно спецификации Java.

Из http://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.21

14.21. Недостижимые Утверждения

Это ошибка времени компиляции, если оператор не может быть выполнен, потому что она недостижима.

Этот раздел посвящен точному объяснению слова "достижимый.- Идея в том, что должна быть какая-то возможная казнь . путь от начала конструктора, метода, экземпляра инициализатор, или статический инициализатор, который содержит утверждение к само утверждение. При анализе учитывается структура заявления. За исключением особого отношения к while, do и для высказывания, выражение условия которых имеет постоянное значение true, то значения выражений не учитываются при анализе потока.

Например, компилятор Java примет код:

{ int n = 5; while (n > 7) k = 2;} даже если значение n известно во время компиляции и в принципе, во время компиляции может быть известно, что назначение к никогда не может быть выполнено.

Правила в этом разделе определяют два технических термина:

Достижимо ли утверждение

Может ли оператор нормально завершаться

Приведенные здесь определения позволяют оператору нормально завершаться только в том случае, если он достижимый.

Чтобы сократить описание правил, обычная аббревиатура "iff" используется для обозначения " если и только если."

Оператор достижимого разрыва выходит из оператора, если в пределах разрыва target, либо нет операторов try, блоки try которых содержат оператор break, или есть операторы try, чьи блоки try содержат инструкцию break и все предложения finally тех, кто пытается заявления могут завершаться нормально.

Это определение основано на логике вокруг " попыток передачи контроль " в §14.15.

Оператор continue продолжает оператор do, если, внутри делать оператор, либо нет операторов try, блоки try которых содержат оператор continue, или есть операторы try, чьи блоки try содержат оператор continue и все предложения finally тех, кто пытается заявления могут завершаться нормально.

Правила следующие:

Блок, являющийся телом конструктора, метода, экземпляра инициализатор, или статический инициализатор достижим.

Пустой блок, который не является блоком коммутатора, может обычно завершать эквивалентность его достижимый.

Непустой блок, который не является блоком коммутатора, может нормально завершить iff последнее утверждение в нем может завершиться нормально.

Первый оператор в непустом блоке, который не является блоком коммутатора, является достижимо, если блок достижим.

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

Локальный класс заявление декларации может завершиться нормально, если это так достижимый.

Оператор объявления локальной переменной может завершаться нормально, если это достижимый.

Пустой оператор может завершаться нормально, если он достижим.

Помеченный оператор может нормально завершиться, если хотя бы один из верно следующее:

Содержащийся оператор может завершаться нормально.

Существует достижимый оператор break, который выходит из помеченного оператора.

Содержащийся оператор достижим, если помеченный оператор является достижимый.

Оператор выражения может завершаться нормально, если он достижим.

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

Оператор then достижим, если оператор if-then является достижимый.

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

Оператор then достижим, если оператор if-then-else является достижимый.

Оператор else достижим, если оператор if-then-else является достижимый.

Эта обработка оператора if, независимо от того, имеет ли он другую часть, довольно необычный. Обоснование приводится в конце этого раздела.

Оператор assert может завершаться нормально, если он достижим.

Оператор switch может нормально завершить хотя бы одно из следующих действий: верно следующее:

Блок переключателей пуст или содержит только метки переключателей.

Последний оператор в блоке коммутатора может завершиться нормально.

Существует по крайней мере одна метка переключателя после последнего блока переключателя группа утверждений.

Блок коммутатора не содержит метки по умолчанию.

Существует достижимый оператор break, который выходит из оператора switch.

Блок коммутатора достижим, если его оператор коммутатора является достижимый.

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

Он имеет метку case или default.

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

Оператор while может нормально завершить хотя бы одно из следующих действий: верно следующее:

Оператор while достижим и условие выражение не является постоянное выражение (§15.28) со значением true.

Существует достижимый оператор break, который выходит из оператора while.

, содержащаяся в заявлении, является достижимой эквивалентностью, в то время как заявление достижимо и выражение условия не является постоянным выражением значение которого false.

Оператор do может нормально завершать iff, по крайней мере, одно из следующих действий верно:

Содержащийся оператор может нормально завершаться и состояние выражение не является постоянным выражением (§15.28) со значением true.

Оператор do содержит достижимый оператор continue с no ярлык, и утверждение do является самым сокровенным while, do, или for заявление, содержащее, что оператор continue, а дальше оператор продолжает этот оператор do, и выражение условия является не является постоянным выражением со значением true.

Оператор do содержит достижимый оператор continue с меткой Л, и оператор do имеет метку L, и оператор continue продолжает то, что делает оператор, и выражение условия не является постоянное выражение со значением true.

Существует достижимый оператор break, который выходит из оператора do.

, содержащаяся в заявлении, является достижимой эквивалентностью заявление сделать достижимый.

Оператор basic for может нормально завершить хотя бы одно из следующих действий: верно следующее:

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

Существует достижимый оператор break, который выходит из оператора for.

Содержащийся оператор достижим, если оператор for является достижимо и выражение условия не является постоянным выражением значение которого false.

Расширенный оператор for может завершаться нормально, если он достижим.

Перерыв, продолжение, возврат или оператор throw не может завершить обычно.

Синхронизированный оператор может нормально завершать содержащийся оператор может обычно завершаться.

Содержащийся оператор достижим, если синхронизированный оператор является достижимый.

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

Блок try может завершиться нормально или любой блок catch может завершиться нормально. обычно.

Если оператор try имеет значение finally блок, то, наконец, блок может завершите нормально.

Блок try достижим, если оператор try достижим.

Блок catch C достижим, если верно следующее:

Либо тип параметра C является непроверенным типом исключения, либо Throwable; или какое-то выражение или оператор throw в блоке try является достижимо и может вызвать проверенное исключение, тип которого присваивается к параметру предложения catch C.

An выражение достижимо, если оно содержится в самом сокровенном высказывании достижимый.

Нормальное и резкое завершение выражений см. в §15.6.

В операторе try нет более раннего блока catch a, такого что тип параметра C такой же, как или подкласс типа A параметр.

Блок блока catch достижим, если блок catch является достижимый.

Если имеется блок finally, он достижим при попытке заявление достижимый.

for(final int z=4;z<6;)
{
}
System.out.println("Test-2"); //unreachable code --> z is final. Its value can't change. There is no way out of that loop



final int z=4;
for(;;)
{
  if(z<2)  // z is 4  . The compiler only knows the value of "z". It doesn't know what z<2 evaluates to.. So, it still thinks taht there is a chance of getting out of that loop.
break;
}
System.out.println("Test-3");  //So --> reachable code.