Я часто обнаруживаю, что при отладке программы удобно (хотя, возможно, и плохая практика) вставлять оператор возврата внутри блока кода. Я мог бы попробовать что-то подобное на 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");
}
}
конечно, это приведет к ошибке компилятора.
Test.java:7: недостижимый оператор
Я мог понять, почему предупреждение может быть оправдано, поскольку неиспользованный код - плохая практика. Но я не понимаю, почему это должно вызывать ошибку.
Это просто Java пытается быть няней, или есть веская причина сделать это ошибкой компилятора?
Ответы:
Потому что недостижимый код не имеет смысла для компилятора. Хотя сделать код значимым для людей и первостепенно и сложнее, чем сделать его значимым для компилятора, компилятор является основным потребителем кода. Разработчики Java придерживаются точки зрения, что код, не имеющий смысла для компилятора, является ошибкой. Их позиция состоит в том, что если у вас есть недостижимый код, вы сделали ошибку, которую необходимо исправить.
Здесь есть аналогичный вопрос: Недостижимый код: ошибка или предупреждение? , в котором автор говорит: «Лично я считаю, что это должна быть ошибка: если программист пишет фрагмент кода, он всегда должен иметь намерение фактически запустить его в каком-либо сценарии». Очевидно, что разработчики языка Java согласны.
Должен ли недостижимый код предотвращать компиляцию - это вопрос, по которому никогда не будет консенсуса. Но именно поэтому разработчики Java сделали это.
Ряд людей в комментариях указывают на то, что существует множество классов недостижимого кода, который Java не препятствует компиляции. Если я правильно понимаю последствия Геделя, ни один компилятор не сможет поймать все классы недостижимого кода.
Модульные тесты не могут отловить каждую ошибку. Мы не используем это как аргумент против их ценности. Точно так же компилятор не может уловить весь проблемный код, но он по-прежнему имеет ценность для предотвращения компиляции плохого кода, когда это возможно.
Разработчики языка Java считают недоступный код ошибкой. Поэтому разумно предотвращать его компиляцию, когда это возможно.
(Прежде чем вы проголосуете против: вопрос не в том, должна ли Java иметь ошибку компилятора недостижимых операторов. Вопрос в том, почему в Java есть ошибка компилятора недостижимых операторов. Не опускайте меня только потому, что вы думаете, что Java приняла неправильное проектное решение.)
источник
return; System.out.println();
иif(true){ return; } System.out.println();
гарантированно будут иметь одинаковое поведение, но одно из них является ошибкой компиляции, а другое - нет. Итак, когда я отлаживаю и использую этот метод для временного «комментирования» кода, я это делаю именно так. Проблема с закомментированием кода заключается в том, что вам нужно найти подходящее место, чтобы остановить свой комментарий, что может занять больше времени, чем оченьreturn;
быстрое добавление .Нет однозначной причины, по которой нельзя допускать недостижимые утверждения; другие языки позволяют их без проблем. Для вашей конкретной потребности это обычный трюк:
if (true) return;
Это выглядит бессмысленно: любой, кто прочитает код, догадается, что это должно быть сделано намеренно, а не из-за небрежной ошибки, когда остальные операторы остаются недоступными.
В Java есть небольшая поддержка «условной компиляции».
http://java.sun.com/docs/books/jls/third_edition/html/statements.html#14.21
источник
if (true) return;
не указывает на то, ПОЧЕМУ вы пропускаете логику, аif (BEHAVIOURDISABLED) return;
выражает намерение.Это няня. Я чувствую, что .Net понял это правильно - он выдает предупреждение о недоступности кода, но не ошибку. Хорошо быть предупрежденным об этом, но я не вижу причин предотвращать компиляцию (особенно во время сеансов отладки, когда неплохо сделать возврат, чтобы обойти некоторый код).
источник
Я только что заметил этот вопрос и хотел добавить к нему свои 0,02 доллара.
В случае Java это вообще не вариант. Ошибка «недоступного кода» возникает не из-за того, что разработчики JVM думали защитить разработчиков от чего-либо или проявлять особую бдительность, а из требований спецификации JVM.
И компилятор Java, и JVM используют так называемые «карты стека» - определенную информацию обо всех элементах в стеке, выделенных для текущего метода. Тип каждого слота стека должен быть известен, чтобы инструкция JVM не использовала элемент одного типа для другого. Это в основном важно для предотвращения использования числового значения в качестве указателя. Возможно, используя сборку Java, попытаться отправить / сохранить число, но затем вывести / загрузить ссылку на объект. Однако JVM отклонит этот код во время проверки класса, то есть когда карты стека создаются и проверяются на согласованность.
Чтобы проверить карты стека, виртуальная машина должна пройти через все пути кода, существующие в методе, и убедиться, что независимо от того, какой путь кода будет когда-либо выполняться, данные стека для каждой инструкции соответствуют тому, что было отправлено любым предыдущим кодом. / хранится в стеке. Итак, в простом случае:
Object a; if (something) { a = new Object(); } else { a = new String(); } System.out.println(a);
в строке 3 JVM проверит, что обе ветви if были сохранены только в (который является просто локальным var # 0) что-то, что совместимо с Object (поскольку именно так код из строки 3 и далее будет обрабатывать локальную var # 0 ).
Когда компилятор доходит до недостижимого кода, он не совсем знает, в каком состоянии стек может быть в этот момент, поэтому он не может проверить его состояние. На этом этапе он больше не может полностью компилировать код, так как он также не может отслеживать локальные переменные, поэтому вместо того, чтобы оставить эту неоднозначность в файле класса, он выдает фатальную ошибку.
Конечно, простое условие вроде
if (1<2)
обманет его, но на самом деле это не обман - оно дает ему потенциальную ветвь, которая может привести к коду, и, по крайней мере, и компилятор, и виртуальная машина могут определить, как элементы стека могут быть использованы оттуда. на.PS Я не знаю, что делает .NET в этом случае, но я считаю, что компиляция тоже не удастся. Обычно это не проблема для компиляторов машинного кода (C, C ++, Obj-C и т. Д.).
источник
{ [flowingstatement;]* }
=>flowingstatement
,{ [flowingstatement;]* stoppingstatement; }
=>stoppingstatement
,return
=>stoppingstatement
,if (condition) stoppingstatement; else stoppingstatement
=>stoppingstatement;
и т. Д.?void blah() { try {return;} catch (RuntimeError ex) { } DoSomethingElse(); }
Java закричит, что не существует способа выхода изtry
блока через исключение, или он решит, что в любомtry
блоке может произойти какое-либо непроверенное исключение ?if (constantThatEqualsFive < 3) {doSomething;};
.Одна из целей компиляторов - исключить классы ошибок. Какой-то недостижимый код появляется случайно, приятно, что javac исключает этот класс ошибок во время компиляции.
Для каждого правила, обнаруживающего ошибочный код, кто-то захочет, чтобы компилятор принял его, потому что они знают, что делают. Это наказание за проверку компилятора, и получение правильного баланса - одна из хитрых точек дизайна языка. Даже при строжайшей проверке можно написать бесконечное количество программ, так что все не может быть так плохо.
источник
Хотя я считаю, что эта ошибка компилятора - это хорошо, есть способ ее обойти. Используйте условие, которое, как вы знаете, будет истинным:
public void myMethod(){ someCodeHere(); if(1 < 2) return; // compiler isn't smart enough to complain about this moreCodeHere(); }
Компилятор недостаточно умен, чтобы жаловаться на это.
источник
1<2
это правда, а остальную часть метода не нужно включать в байтовый код. правила «недостижимых операторов» должны быть четкими, фиксированными и независимыми от сообразительности компиляторов.Конечно, хорошо жаловаться, что чем строже компилятор, тем лучше, поскольку он позволяет вам делать то, что вам нужно. Обычно небольшая цена - это закомментировать код, а выигрыш в том, что когда вы компилируете код, он работает. Общий пример - 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, поэтому нет необходимости устанавливать флаг DEBUG в коде, а только путем добавления аргумента во время выполнения, что полезно, когда целью не является машина разработчика и перекомпиляция и передача байт-кода требует времени.Есть также
System.exit(0)
способ, но это может быть излишним, если вы поместите его в Java в JSP, он завершит работу сервера.Помимо того, что Java изначально является языком «няни», я бы предпочел использовать что-то родное, например C / C ++, для большего контроля.
источник
static final
переменной, которая установлена в статическом блоке инициализации, наstatic final
переменную, которая установлена в ее объявлении, не должно быть критическим изменением. Вполне вероятно, что при первом написании класса он мог иногда быть неспособным что-то сделать (и до времени выполнения не было известно, сможет ли он это сделать или нет), но более поздние версии класса могли быть в состоянии делайте это действие всегда. ПереходmyClass.canFoo
на константу должен сделать егоif (myClass.canFoo) myClass.Foo(); else doSomethingElse();
более эффективным, а не нарушить его.