Почему Java имеет ошибку компилятора "недостижимый оператор"?



Я часто нахожу, что при отладке программы удобно (хотя, возможно, плохая практика) вставлять оператор return внутри блока кода. Я мог бы попробовать что-то подобное в Java ....



class Test {
public static void main(String args[]) {
System.out.println("hello world");
return;
System.out.println("i think this line might cause a problem");
}
}


конечно, это приведет к ошибке компилятора.




438   8  

8 ответов:

потому что недостижимый код не имеет смысла для компилятора. В то время как сделать код значимым для людей является как первостепенным, так и более сложным, чем сделать его значимым для компилятора, компилятор является основным потребителем кода. Разработчики Java считают, что код, который не имеет смысла для компилятора, является ошибкой. Их позиция заключается в том, что если у вас есть какой-то недостижимый код, вы сделали ошибку, которую необходимо исправить.

здесь есть аналогичный вопрос: недостижимый код: ошибка или предупреждение?, в котором автор говорит: "лично я сильно чувствую, что это должна быть ошибка: если программист пишет кусок кода, он всегда должен быть с намерением фактически запустить его в каком-то сценарии."Очевидно, что разработчики языка Java согласны.

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


A количество людей в комментариях указывают, что есть много классов недостижимого кода Java не препятствует компиляции. Если я правильно понимаю последствия Геделя, ни один компилятор не может поймать все классы недостижимого кода.

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

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


(перед вами downvote: вопрос не в том, Должна ли Java иметь ошибку компилятора недостижимого оператора. Вопрос в том почему Java имеет недостижимую ошибку компилятора оператора. Не опускайте меня только потому, что вы думаете, что Java сделал неправильное дизайнерское решение.)

нет никакой окончательной причины, по которой недостижимые утверждения не должны быть разрешены; другие языки позволяют их без проблем. Для вашей конкретной потребности, это обычный трюк:

if (true) return;

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

Java немного поддерживает " условный компиляция"

http://java.sun.com/docs/books/jls/third_edition/html/statements.html#14.21

if (false) { x=3; }

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

обоснование этого различия лечение заключается в том, чтобы позволить программистам определите "переменные флага", такие как:

static final boolean DEBUG = false;

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

if (DEBUG) { x=3; }

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

Это няня. Я чувствую, что .Net получил это право - он вызывает предупреждение для недостижимого кода, но не ошибку. Хорошо быть предупрежденным об этом, но я не вижу причин предотвращать компиляцию (особенно во время сеансов отладки, где приятно бросать возврат, чтобы обойти некоторый код).

Я только что заметил этот вопрос, и хотел добавить мой $.02 для этого.

в случае Java это вообще не вариант. Ошибка "недостижимый код" происходит не от того, что разработчики JVM думали защитить разработчиков от чего-либо или быть особенно бдительными, а от требований спецификации JVM.

как компилятор Java, так и JVM используют так называемые "карты стека" - определенную информацию обо всех элементах стека, выделенных для современный метод. Тип каждого слота стека должен быть известен, так что инструкция JVM не будет плохо обращаться с элементом одного типа для другого типа. Это особенно важно для предотвращения использования числового значения в качестве указателя. Можно, используя сборку Java, попытаться нажать / Сохранить число, но затем pop/загрузить ссылку на объект. Однако JVM отклонит этот код во время проверки класса, то есть когда создаются и тестируются карты стека консистенция.

чтобы проверить карты стека, виртуальная машина должна пройти через все пути кода, которые существуют в методе, и убедиться, что независимо от того, какой путь кода когда-либо будет выполнен, данные стека для каждой инструкции согласуются с тем, что любой предыдущий код толкнул/сохранил в стеке. Итак, в простом случае:

Object a;
if (something) { a = new Object(); } else { a = new String(); }
System.out.println(a);

в строке 3 JVM проверит, что обе ветви " if " хранятся только в A (который является только локальным var#0) , что совместимо с объектом (поскольку именно так код из строки 3 и дальше будет обрабатывать локальный var#0).

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

конечно простое условие, как if (1<2) дурачок, но это не действительно обманывает - это дает ему потенциальную ветвь, которая может привести к коду, и по крайней мере как компилятор, так и виртуальная машина могут определить, как элементы стека могут использоваться оттуда.

P. S. Я не знаю, что .Сетка в этом случае, но я считаю, что это будет не сборник, а также. Это обычно не будет проблемой для любых компиляторов машинного кода (C, C++, Obj-C и т. д.)

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

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

хотя я думаю, что эта ошибка компилятора-хорошая вещь, есть способ обойти ее. Используйте условие, которое, как вы знаете, будет истинным:

public void myMethod(){

    someCodeHere();

    if(1 < 2) return; // compiler isn't smart enough to complain about this

    moreCodeHere();

}

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

конечно, хорошо жаловаться, чем строже компилятор, тем лучше, поскольку он позволяет вам делать то, что вам нужно. Обычно небольшая цена, чтобы заплатить, чтобы прокомментировать код, выгода заключается в том, что при компиляции кода работает. Общим примером является Haskell, о котором люди кричат, пока не поймут, что их тест/отладка-это только основной тест и короткий. Я лично в Java почти не делаю отладки, будучи (на самом деле нарочно) не внимательным.

если причина для разрешения if (aBooleanVariable) return; someMoreCode; Это разрешить флаги, то факт, что if (true) return; someMoreCode; не генерирует ошибку времени компиляции кажется несогласованностью в политике генерации CodeNotReachable исключения, так как компилятор "знает", что true это не флаг (не переменной).

два других способа, которые могут быть интересны, но не действуют на отключение части кода метода, а также if (true) return:

теперь, вместо того чтобы сказать if (true) return; вы можете сказать assert false и добавить -ea OR -ea package OR -ea className к аргументам jvm. Хороший момент заключается в том, что это позволяет обеспечить некоторую детализацию и требует добавления дополнительного параметра к вызову jvm, поэтому нет необходимости устанавливать флаг отладки в коде, но добавляя аргумент во время выполнения, что полезно, когда цель не является машиной разработчика, а перекомпиляция и передача байт-кода занимает время.

есть еще System.exit(0), но это может быть излишним, если вы поместите его в Java в JSP, то он будет завершите работу сервера.

кроме того, что Java является по дизайну языком "няни", я бы предпочел использовать что-то родное, например C/C++ для большего контроля.

Comments

    Ничего не найдено.