“if”语句末尾的分号

Semicolon at end of 'if' statement

提问人:Erik Bergsten 提问时间:1/2/2013 最后编辑:double-beepErik Bergsten 更新时间:4/18/2019 访问量:52748

问:

今天,在搜索了半个小时的 bug 之后,我发现可以在 if 语句后面加上一个分号而不是代码,如下所示:

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

这基本上意味着无论是否相等,这些事情都会完成,而这种说法没有任何意义。为什么 Java 不给我错误?在什么情况下这样做会有用吗?abif

java if 语句

评论

1赞 Scorpion 1/2/2013
看起来像一个无操作,即如果 a 和 b 相同,则什么都不做;您可以在那里添加一个 javadoc,但我想不出任何其他用途
12赞 gefei 1/2/2013
不,这没有任何情况是有用的。为什么?如果我在 Java 中不理解的每一件事都得到一毛钱:)
4赞 bonCodigo 1/2/2013
一般规则是分号(;)完成语句。所以在那之后什么也没发生if
2赞 Paddy3118 1/2/2013
啊哈!这是 Python 语法的错误 - 视觉缩进显示块范围,这使得这种错误在 Python 中不太可能发生,因为一般来说,如果代码块没有缩进到 if 语句中,那么它就不在 if 语句中。
0赞 Mukul Goel 1/2/2013
@gefei :没有这种情况是有用的,真的。但在某些情况下,这可能会(或被用来)影响程序。请看我的回答。

答:

92赞 Marcin Szymczak 1/2/2013 #1

为什么会这样?

Java 语言规范说:

空语句

空语句不执行任何操作。

EmptyStatement:
    ;

空语句的执行始终正常完成

它本质上意味着你要执行空语句,如果 a==b

if(a == b);

你应该怎么做:

这个问题有两种主要的解决方案:

  1. 通过使用代码格式化程序,可以避免空语句的问题 和周围的东西里面有和.通过这样做 你的空洞陈述将更具可读性。if{}

    if(a == b){
      ;
    }
    
  2. 您还可以检查用于静态代码分析的工具,例如:

    他们可以立即突出显示诸如此类的问题。

我建议将这两种解决方案结合起来。

评论

7赞 Patricia Shanahan 1/2/2013
即使是最简单的解决方案,使用代码格式化程序,也可以解决这个问题。打算放在 if 内的语句将与 if 出现在相同的缩进处。
1赞 Marcin Szymczak 1/2/2013
当然,但我建议同时使用格式化程序和静态代码分析。
9赞 AgilePro 1/2/2013
你不能通过使用大括号来避免这种情况,因为在右括号之后和左大括号之前的意外分号是一个语法上有效的程序......而且可能不是你想要的。但是,我同意 matter 代码可能有助于避免这个问题。
5赞 Peter Lawrey 1/2/2013 #2

我想不出它有用的场合。它对于像这样的循环很有用

 while(do something);

 for(init; do something; something else);

如果您经常在 IDE 中使用代码格式,这些类型的错误就会变得很明显。一些 IDE 也强调这是一个可能的错误。

29赞 Tim M. 1/2/2013 #3

在什么情况下这样做会有用吗?

有用?就像“让你的代码更干净、更清晰、更快、更易于维护”一样?一点也不。这很可能是糟糕的、令人困惑的代码

但这不一定是良性的。由于引起副作用的方法,此类语句可以执行操作和/或更改状态,并且可以选择性地评估由于运算符短路而导致的方法。

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

在这里,或者可以做一些事情,并且只有在为真时才会执行。a()b()b()a()

至于为什么,我认为答案很简单,偏离定义的预期行为(例如,像 这样的语句)比开发人员编写糟糕代码的替代方案更糟糕。while(reader.read());

编写糟糕的代码总是可能的。重申一下,这几乎在任何情况下都是糟糕的代码。

1赞 Matt Clark 1/2/2013 #4
if(a==b)
    println("a equals b");

如果只有一行要执行,则可以使用不带 IF 语句的 IF 语句,因此通过使用 if they equal, execute 和 empty 语句...因此,它不会执行任何操作,然后返回到 IF 块之外的正常循环。{}if(a==b);

评论

7赞 user 1/2/2013
println("a now equals b");
8赞 André Stannek 1/2/2013 #5

如果使用语句,则如果条件为 true,则将执行 之后的第一条语句。如果 后面有一个块(带大括号),则它计入整个块。如果没有块,则仅计入一个语句。单个分号是空语句。你也可以从你的示例中编写代码,如下所示:ififif

if(a==b) {
    ;
}
4赞 yshavit 1/2/2013 #6

我同意你的看法,这对人类来说没有用处。我怀疑它的存在是因为它简化了语言定义;例如,这意味着 an 之后的事物与 a 之后的事物 e 相同。ifwhile

19赞 gefei 1/2/2013 #7

可能的用例:

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

不好,但有可能。

不过,我确实认为 Java 规范应该不允许空的 .if

评论

3赞 tudor -Reinstate Monica- 1/2/2013
像这样的代码实际上可以通过考虑所有情况来防止逻辑错误。“如果真的什么都不做,否则......”可以更具可读性,因为您不会被否定错误和“遗漏案例”所迷惑。如今,大多数编译器都知道这种结构,并且无论如何都会为您反转以提高速度。例如,水星语言强制执行了这一点!
2赞 yshavit 1/6/2013
@tudor 我想说的是,即使对于那个用例,也最好这样做,因为更明显的是,no-op 是故意的,而不是错别字。if (a==b) { // do nothing } else { doSomething(); }
0赞 tudor -Reinstate Monica- 1/6/2013
@yshavit 这是真的。很多时候,注释有助于使事情更清晰,但这与此结构不同。此外,if (a==b) 之间没有功能差异;什么都不做,如果 (a==b) { /*什么都不做*/ } 两者都将通过删除注释和空大小写并反转条件来优化。
0赞 yshavit 1/6/2013
@tudor 对于编译器来说,是的,毫无疑问。但让我这样说:如果我看到有人按照我的方式做,我会想“这个人一定认为这样表达条件更容易。如果我看到他们使用分号+else-braces 语法,我会检查 VCS 日志以确保它不是其他人后来添加 else 子句的错别字/错误。
7赞 Edwin Buck 1/2/2013 #8

这是在有更多的句法糖来区分表达式和语句的时代遗留下来的。

基本上,逗号用作列表项分隔符,因此分号用作“语句列表”分隔符。缺点在于处理列表中的 null 项和块中的 null 语句。

在项目列表中,Java 使用 explicit 关键字,但“null 语句”只是一个空行。允许空行的存在是从 C 继承的传统遗留下来的。null

为什么要这样做?特别是当你知道没有语句被执行时,语句:因为一些 if 语句有副作用:if

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

是的,这不是最好的例子,但基本上它说从流中读取一个字节并且什么都不做。在某些极端情况下可能很有用,但即使这个例子不是最好的,它也说明了意图。我们希望在不意外执行任何语句的情况下感受到表达式的副作用。

2赞 AgilePro 1/2/2013 #9

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 的定义方式。

-1赞 Narayan Bhandari 1/2/2013 #10

末尾的分号,
if(a==b);只需在单行中完成语句,这意味着忽略条件的结果并从下一行
继续执行此代码很有用,另一方面有时会在程序中引入错误,例如案例

1。

a = 5;
b = 3;
if(a == b);
prinf(“A 和 B 相等”);

案例 2.

a = 5;
b = 5;
if(a == b);
prinf(“A 和 B 相等”);
会在屏幕上打印相同的输出...

评论

0赞 vegemite4me 1/2/2013
“此代码很有用” <- 忽略条件的结果怎么可能有用?
0赞 Narayan Bhandari 9/18/2014
是的,在if-elseif层次结构中,如果我们需要忽略某些条件的结果,则可以使用。例如
3赞 user34537 1/2/2013 #11

为什么?这是因为它对编译器编写者来说更容易。您不必在之后使用特殊情况来检查分号,并且具有允许的附加用法if(cond)

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

尽管允许这样做实际上是一个糟糕的主意。允许然后添加案例来检查这一点更容易。

评论

0赞 jmoreno 1/2/2013
+1,但用法示例是不必要的。正如你所展示的,它可以被使用,但它远非组织该代码的最佳方式。它很丑陋,但没有理由为了拒绝而对它进行特殊处理——至少从编译器的 POV 来看是这样。从 stle POV...
0赞 Parvez 1/2/2013 #12

我可以想到一个需要空语句的场景(不是条件,而是循环)。ifwhile

当程序只想从用户那里得到明确的确认才能继续时。当用户确认后的工作依赖于其他一些事情并且用户想要控制何时继续时,这可能是必需的。

    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
2赞 Mukul Goel 1/2/2013 #13

仅供参考,如果有这样的声明,它会产生或可以产生什么影响

考虑一段如下代码。

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

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

显然,在这种情况下,该语句确实会更改输出。因此,这样的声明可以有所作为。if

在这种情况下,这可能很有用,或者更准确地说对程序有影响。

11赞 nullptr 5/8/2013 #14

如果你使用的是 Eclipse,你可以让它警告你这些语句:

Java->Compiler->Errors/Warnings

1赞 user4668606 5/12/2016 #15

jls 中的一些定义对此进行了解释(第 14 章):

块是语句

如上所述,a 是 ,而 是 ,而 是 。因此,无论需要其中任何一个,我们都可以插入一个 .BlockStatementWithoutTrailingSubstatementStatementNoShortIfStatementBlock

if 子句

虽然 和 -loops 也是如此,但我将使用 -语句。这些规则几乎是一样的。的语法描述可以在这里找到。forwhileifif-statements

IfThenStatement:
    if ( Expression ) Statement

IfThenElseStatement:
    if ( Expression ) StatementNoShortIf else Statement

IfThenElseStatementNoShortIf:
    if ( Expression ) StatementNoShortIf else StatementNoShortIf

因此,我们可以在这里使用我们的块。

但是为什么它适用于 ; ?

;定义为 (link),它也是 .因此,在条件代码片段中,如 和 循环,如果需要 或,我们可以用 a 替换 a。EmptyStatementStatementNoShortIfif-statementBlockEmptyStatementStatementNoShortIfStatement

因此有效。if(Expression)EmptyStatement

为什么这不会给出错误?

很简单:如果 java 发现无效语法,它就会给出错误。但是完全有效的语法。相反,如果使用正确的参数启动,则会发出警告。可以禁用/启用的警告的完整列表列出了用于此目的的警告名称。因此,编译 or 将生成有关此的警告。if(Expression)EmptyStatementjavacempty-Xlint:all-Xlint:empty

您的 IDE 也应该有一个选项来启用此类警告。 对于 eclipse,请参阅 @nullptr 的答案。在 IntelliJ 中,您可以按 ,进入搜索字段并启用警告(在图像中标记)Ctrl + Shift + Aempty body

IntelliJ enable empty-body warning

这到底是干什么用的?

老实说,从极简主义的角度来看,它没有多大用处。通常有一种方法可以在没有“什么都不做”命令的情况下完成工作。这更像是个人喜好的问题,你是否愿意使用

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

if( a() ) b();

这同样适用于使用其他情况。关于这个主题,要考虑的一个重要点是代码的可读性。在某些情况下,通过使用 no-op 使代码更具可读性。另一方面,在某些情况下,使用 - 上面的例子将计入后来的 IMO。EmptyStatementEmptyStatement

-2赞 George C 6/27/2017 #16

在为课堂进行编程作业时,我正在使用 N x N 的涂鸦网格,并将随机涂鸦的特征与上面、下面、左边和右边的特征进行比较,我发现这是一个很好的用途,可以防止嵌套语句和潜在的边界异常。我的目标是尽量减少代码并避免嵌套 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]));

在 A 和 B 之间进行某些操作的位置。method(Doodad a, Doodad b)

或者,您可以使用异常处理来避免这种语法,但它对我的应用程序有效且效果很好。

评论

1赞 intcreator 6/28/2017
if(row != 0) method (grid[row][col], grid[row-1][col]);在不使用空语句的情况下将具有相同的效果。if
0赞 DMW 3/10/2019 #17

看这个:

int a,b,c = 0;
if(a == b){
   c =1;
} 
System.out.print(c);//1

所以,你可以这样写:

if (a == b)c=1;

但是,如果这段代码是这样的:

int a,b,c=0;
if (a != b){
}
if (a == b ){
  c =1;
}

你可以这样写:

if(a != b);
if(a == b )c=1;

所以,你会知道做注意if(a != b);

0赞 Bishal Jaiswal 4/18/2019 #18

if 中的分号表示 if 条件的终止,就像 java 中一样,被视为语句的结束,因此 if 之后的语句被执行。;