2012-02-14 2 views
24

Следующий код выдает ошибку unreachable statement компилятораНедоступен код

public static void main(String[] args) { 
    return; 
    System.out.println("unreachable"); 
} 

Иногда для целей тестирования хотения предотвратить метод от вызова, поэтому быстрый способ сделать это (вместо того, чтобы комментировать это везде он используется) должен немедленно вернуться из метода, чтобы метод ничего не делал. То, что я тогда всегда сделать, чтобы получить Arround ошибки компилятора это

public static void main(String[] args) { 
    if (true) { 
     return; 
    } 
    System.out.println("unreachable"); 
} 

Я просто любопытно, почему это ошибка компилятора ?? Будет ли он каким-то образом разбивать Java-байт-код, защищать ли он программиста или это что-то еще?

Также (и это для меня более интересно), если компиляция java в байт-код делает любую оптимизацию (или даже если это не так), то почему бы не обнаружить вопиющий недостижимый код во втором примере? Что было бы псевдокодом компилятора для проверки того, что заявление недостижима?

+0

вы можете прочитать раздел 14.16 на этой странице: http://java.sun.com/docs/books/jls/second_edition/html/statements.doc.html – Johnydep

+0

Спасибо за ссылку. Я думаю, что я застрял в мышлении «ассемблера», потому что мне трудно понять, как «прыжки», вызванные вызовом метода, оператор 'if' и' return' могут позволить обнаружить недостижимую строку в первом но не во втором. – ughzan

+1

Хорошее обходное решение с if (true) thingie .... – Ted

ответ

22

Недоступный код не имеет смысла, поэтому ошибка времени компиляции полезна. Причина, по которой он не будет обнаружен во втором примере, как и вы ожидаете, предназначен для тестирования/отладки. Это объясняется в описании:

if (false) { x=3; } 

не приводит к ошибке времени компиляции.Оптимизирующий компилятор может понимать, что утверждение x = 3; никогда не будет выполнен и может выбрать , чтобы опустить код для этого оператора из сгенерированного файла класса, но утверждение x = 3; не считается «недостижимым» в указанном здесь техническом значении .

Основания для такого различного лечения, чтобы позволить программистам определить «переменный флаг», такие как:

static final boolean DEBUG = false; 

, а затем написать код, такие как:

if (DEBUG) { x=3; } 

Идея заключается в том, что оно должно быть возможно изменить значение DEBUG от false до true или от true до false, а затем скомпилировать код без каких-либо изменений текста программы.

Ссылка: http://docs.oracle.com/javase/specs/jls/se8/html/jls-14.html#jls-14.21

+0

Интересно прочитать (из вашей справки), что только оператор 'if' рассматривается как частный случай в отношении тестирования на недостижимый код. И я могу понять, что должно быть сделано исключение для 'if (DEBUG)', но почему также для 'if (true)'? Думаю, это было просто проще. Благодарю. – ughzan

+3

'if (DEBUG)' это то же самое, что и 'if (true)'. 'DEBUG' - постоянная переменная, потому что она является окончательной и инициализирована выражением постоянной времени компиляции. 'true' является литералом примитивного типа, а также константным выражением. Даже было возможно различать их, что могло бы вызвать путаницу. Люди спрашивали: почему: if (DEBUG) '**, но не **' if (true) '? –

+0

Отличный ответ ... –

-1

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

+8

Это не объясняет, почему это ошибка вместо предупреждения. – CodesInChaos

2

Эта ошибка в основном предотвращает ошибки программиста (своп из двух строк или более). Во втором фрагменте вы даете понять, что вас не интересует system.out.println().

+0

Но может ли второй отрывок не быть ошибкой? Например, если оставить его непреднамеренно. – ughzan

+0

Да, это может быть так, но обычно программисты делают это, чтобы отключить/включить некоторые функции, и это гораздо более очевидно, чем раньше. –

2

Будет ли это прерывать Java-байт-код каким-либо образом, защищать программиста или это что-то еще?

Это не требуется для Java/JVM. Единственная цель этой ошибки компиляции - избегать глупых ошибок программиста. Рассмотрим следующий код JavaScript:

function f() { 
    return 
     { 
      answer: 42 
     } 
} 

Эта функция возвращает undefined как двигатель JavaScript добавляет точку с запятой в конце строки и игнорирует мертвую код (как он считает). Компилятор Java более умный, и когда он обнаруживает, что вы делаете что-то явно и явно неправильно, он не позволит вам сделать это. На земле у вас нет способа иметь мертвый код. Это как-то вписывается в предпосылку Java быть безопасным языком.

+0

Почему второй фрагмент не вызывает ошибку?Я не думаю, что было бы сложнее обнаружить (но я могу ошибаться). – ughzan

+0

О, но это обнаружено. Если вы хотите доказать, скомпилируйте свой код с if (true), а затем декомпилируйте его с помощью 'jad', и вы увидите, что компилятор удаляет мертвый код –

7

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

+0

+1: его, чтобы защитить вас от выполнения чего-то, что явно не так. –

+1

Но это может быть не так, если это просто быстрый тест. – fallaciousreasoning

0

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

Во втором коде я поставил заявление выше возвращения и его работа теперь :)

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

государственной статической силы основных (String []) {арг

return; 
System.out.println("unreachable"); 

}

/////////////////////// //////////

государственной статической силы основных (String []) {арг

System.out.println("unreachable"); // Put the statement before return 
return; 

}