Точка с запятой в конце оператора' if'



сегодня, после получаса поиска ошибки, я обнаружил, что можно поставить точку с запятой после оператора if вместо кода, например:



if(a == b);
// Do stuff


что в основном означает, что материал будет выполнен независимо от того, равен ли a b или нет, и оператор if не имеет никакого смысла. Почему Java не дает мне ошибку? Есть ли ситуация, в которой это было бы полезно?

710   16  

16 ответов:

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

Спецификация Языка Java говорит, что:

Пустое Заявление

пустой оператор ничего не делает.

EmptyStatement:
    ;

выполнение пустого оператора всегда завершается нормально

это по существу означает, что вы хотите выполнить пустой оператор, если a==b

if(a == b);

что делать:

есть два основные решения этой проблемы:

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

    if(a == b){
      ;
    }
    
  2. вы также можете увидеть инструменты, используемые для статического анализа кода, такие как:

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

Я бы рекомендовал объединить оба решения.

есть ли ситуация, в которой это было бы полезно?

полезное? Как в "делает ваш код чище, яснее, быстрее, более ремонтопригодным"? Нисколько. Это, скорее всего,плохой, запутанный код.

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

if( a() && b() );

здесь a() или b() может сделать что-то, и b() будет выполняться только если a() - Это правда.

как почему, я думаю, что ответ просто заключается в том, что было бы хуже отклоняться от определенного, ожидаемого поведения (например, такие утверждения, как while(reader.read());), чем альтернатива разработчиков, пишущих плохой код.

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

возможный вариант использования:

if (a==b);
else {
  // Do something
}

не очень хорошо, но возможно.

тем не менее, я думаю, что спецификация Java должна запретить пустой if.

Если вы используете Eclipse, вы можете заставить его предупредить вас об этих утверждениях:

Java->Compiler->Errors/Warnings

если вы используете if оператор, первый оператор после if будет выполнено, если условие истинно. Если у вас есть блок после if (с фигурными скобками), это имеет значение для всего блока. Если блока нет, он считается только для одного оператора. Одна точка с запятой-это пустой оператор. Вы также можете написать код из вашего примера следующим образом:

if(a==b) {
    ;
}

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

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

В списке элементов Java использует явное ключевое слово null, но "нулевой оператор" - это просто пустая строка. Позволять существование пустой строки является пережитком традиции, унаследованной от C.

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

 int c;
 if ((c = in.read()) != -1);

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

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

 while(do something);

или

 for(init; do something; something else);

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

Я согласен с вами, что нет никакой полезной цели для человека. Я подозреваю, что это там, потому что это упрощает определение языка; это означает, что вещь, которая приходит после if Это e то же самое, что приходит после a while, например.

почему? Это потому, что его проще для компилятора писателей. Вам не нужно особого случая, чтобы проверить точку с запятой после if(cond) и имеет дополнительное использование разрешения

if (cond && maybeFunc())
    ;// Code here I want to ignore

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

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

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

while (condition);
{
    statement;
    statement;
}

точка с запятой в конце первой строки была опечаткой, случайно сделав блок оператора для цикла while пустым. Поскольку синтаксис действителен, программа скомпилирована и работает нормально, просто не так, как я хотел. Это было действительно трудно найти.

Я могу придумать ситуации, где это очень приятно что вам разрешено иметь пустые блоки, и это что-то вроде это:

if (condition1) {
    do_action_1();
}
else if (condition2) {
    //nothing really to do in this case
}
else if (condition3) {
    do_action2();
}
else {
    do_action3();
}

В приведенном выше примере, вы хотите, чтобы иметь возможность отделить различные условия. Помните, что эти условия могут перекрываться, поэтому не всегда возможно изменить порядок. Если одно из условий действительно ничего не нужно делать, то хорошо, что Java позволяет иметь пустой блок. В противном случае, язык будет нуждаться в какой-то форме метода "noop", чтобы использовать, когда вы действительно не хотите ничего делать.

Я лично предпочел бы явный оператор "noop" - но это не то, как определяется Java.

просто FYI о юзабилити и какая разница, если есть такое утверждение

рассмотрим фрагмент кода, как показано ниже.

int a = 10;
if ((a = 50) == 50);

System.out.println("Value of a = " + a);

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

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

if(a==b)
    println("a equals b");

вы можете использовать оператор IF без {} если есть только одна строка для выполнения, поэтому с помощью if(a==b); вы говорите, если они равны, выполнить и пустое заявление... Поэтому он ничего не будет делать, а затем вернется к обычному циклу, вне блока IF.

несколько определений из jls объясняют это (Глава 14):

блоки отчетность

как заявил здесь, a Block - это StatementWithoutTrailingSubstatement, который в свою очередь является StatementNoShortIf, который является Statement. Таким образом, где бы любой из них требуется, мы можем вставить тег Block.

предложение if

хотя это также относится и к for и while-петли, я использую if-заявления. Эти правила в значительной степени одинаковы. Этот синтаксическое описание if-statements можно найти здесь.

IfThenStatement:
    if ( Expression ) Statement

IfThenElseStatement:
    if ( Expression ) StatementNoShortIf else Statement

IfThenElseStatementNoShortIf:
    if ( Expression ) StatementNoShortIf else StatementNoShortIf

так что мы можем использовать наш блок здесь.

но почему он работает с ; ?

; определяется как EmptyStatement (ссылке), который также является StatementNoShortIf. Так что в условных кусках кода, как if-statement и петли, мы можем заменить a Block С EmptyStatement, если a StatementNoShortIf или это.

if(Expression)EmptyStatement завод.

почему это не дает ошибку?

довольно просто: java дает ошибку, если он находит недопустимый синтаксис. Но if(Expression)EmptyStatement совершенно правильный синтаксис. Вместо этого javac выдает предупреждение при запуске с соответствующими параметрами. Элемент полный список предупреждений, которые могут быть отключены перечисляет предупреждение-имя empty для этой цели. Так что компиляция с -Xlint:all или -Xlint:empty выдаст предупреждение об этом.

ваша IDE должна иметь возможность включить этот вид предупреждения, а также. Для eclipse см. @nullptr ответ. В IntelliJ, вы можете нажать Ctrl + Shift + A введите empty body в поле поиска и включить предупреждение (отмечено на изображении)

IntelliJ enable empty-body warning

для чего это вообще используется?

честно говоря, там не так много пользы в нем с минималистской точки зрения. Обычно есть способ сделать все без команды" ничего не делать". Это скорее вопрос личных предпочтений, предпочитаете ли вы использовать

if( a() && b() );

или

if( a() ) b();

и то же самое относится к другим случаям, в которых это. Важным моментом, который следует учитывать в этой теме, является читаемость кода. Бывают случаи, когда код становится более читаемым с помощью ОП. С другой стороны бывают случаи, когда код становится гораздо труднее постичь с помощью EmptyStatement - приведенный выше пример будет считаться более поздним ММО.

точка с запятой в конце,
если (a= = b); просто закончите оператор в одной строке, что означает игнорировать результат условия и продолжить выполнение из следующей строки
Этот код полезен, с другой стороны когда-нибудь ввести баг в программу, например,

корпус 1.

a = 5;
b = 3;
если (a = = b);
prinf ("a и b равны");

корпус 2.

a = 5;
b = 5;
Если(а == б);
prinf ("a и b равны");
будет печатать тот же вывод на экран...

Я могу придумать сценарий, где требуется пустой оператор (не для if состоянии, но для while петли).

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

    System.out.println("Enter Y to proceed. Waiting...");
    System.out.println("");

    while(!(new Scanner(System.in).next().equalsIgnoreCase("Y")));

    System.out.println("Proceeding...");
    // do the work here

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

if (row == 0); 
else (method (grid[row][col], grid[row-1][col]));
if (row == N-1);
else (method (grid[row][col], grid[row+1][col]));
if (col == 0);
else (method (grid[row][col], grid[row][col-1]));
if (col == N-1);<br>
else (method (grid[row][col], grid[row][col+1]));

здесь method(Doodad a, Doodad b) выполняет некоторые операции между a и b.

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

Comments

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