分号在'if'语句结束时

时间:2013-01-01 17:22:12

标签: java if-statement

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

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

这基本上意味着无论a是否等于b,都会完成这些工作,if语句没有任何意义。为什么Java没有给我一个错误?是否有任何可能有用的情况?

18 个答案:

答案 0 :(得分:84)

为什么会这样?

Java Language Specification说:

  

空声明

     

空语句什么都不做。

EmptyStatement:
    ;
     

执行空语句总是正常完成

它实质上意味着你想要在== b

时执行空语句
if(a == b);

你应该怎么做:

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

  1. 使用代码格式化程序可以避免空语句出现问题 以及if{}内的周围内容。通过做这个 你的空语句将更具可读性。

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

    他们可以立即突出显示此问题。

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

答案 1 :(得分:28)

  

是否有任何可能有用的情况?

有用的?如“使您的代码更清晰,更清晰,更快速,更易于维护”?一点也不。这很可能是糟糕,令人困惑的代码

但它不一定是良性的。由于导致副作用的方法,此类语句可以执行操作和/或更改状态,并可选择根据short-circuiting of operators评估这些方法。

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

此处,a()b()可能会执行某些操作,b()只会在a()为真时执行。

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

始终可以编写错误的代码。而且重申一下,几乎在任何情况下这都是糟糕的代码。

答案 2 :(得分:19)

可能的用例:

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

不好,但可能。

尽管如此,我认为Java规范应该禁止空if

答案 3 :(得分:11)

如果你正在使用Eclipse,你可以让它警告你这些陈述:

Java->Compiler->Errors/Warnings

答案 4 :(得分:7)

如果使用if语句,如果条件为真,则将执行if之后的第一个语句。如果在if之后有一个块(带花括号),则它会计入整个块。如果没有阻止,则只计算一个语句。单个分号是一个空语句。您也可以像这样编写代码:

if(a==b) {
    ;
}

答案 5 :(得分:6)

从存在更多语法糖以区分表达和陈述的日子开始,这是一个古老的遗留物。

基本上,逗号用作列表项分隔符,因此分号用作“语句列表”分隔符。缺点是处理列表中的空项,以及块中的空语句。

在项列表中,Java使用显式关键字null,但“空语句”只是一个空行。允许存在空行是继承自C的传统。

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

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

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

答案 6 :(得分:5)

我想不出它有用的场合。它对于像

这样的循环很有用
 while(do something);

 for(init; do something; something else);

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

答案 7 :(得分:4)

我同意你的观点,对于人类来说,这没有用处。我怀疑它在那里因为它简化了语言定义;这意味着if之后的事物与while之后的事物相同。

答案 8 :(得分:3)

为什么呢?这是因为编译器编写者更容易。您不必在if(cond)之后设置特殊情况来检查分号,并且添加了允许使用的分号

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

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

答案 9 :(得分:2)

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

答案 10 :(得分:2)

只是关于可用性的一个FYI和 如果有这样的声明它会产生或可以产生什么差异

考虑以下代码。

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

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

显然,在这种情况下,if语句会改变输出。所以这样的声明可以有所作为。

在这种情况下,这对于对计划产生影响可能更有用或更好。

答案 11 :(得分:1)

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

如果只有一行要执行,则可以使用不带{}的IF语句,因此使用if(a==b);表示如果它们相等,则执行并清空语句...所以它什么都不做,然后回到IF块之外的正常循环。

答案 12 :(得分:1)

jls中的一些定义解释了这一点(第14章):

块是语句

如上所述hereBlockStatementWithoutTrailingSubstatement,而StatementNoShortIf又是StatementBlock。因此,只要需要这些,我们就可以插入for

if-clause

虽然whileif - 循环的情况也是如此,但我会使用if-statements - 语句。这些规则几乎相同。可以找到IfThenStatement: if ( Expression ) Statement IfThenElseStatement: if ( Expression ) StatementNoShortIf else Statement IfThenElseStatementNoShortIf: if ( Expression ) StatementNoShortIf else StatementNoShortIf 的语法描述here

;

所以我们可以在这里使用我们的块。

但为什么会这样; ?

EmptyStatement定义为StatementNoShortIflink),也是if-statement。因此,在条件代码段中,如Block和循环,如果需要EmptyStatementStatementNoShortIf,我们可以用Statement替换if(Expression)EmptyStatement。< / p>

因此if(Expression)EmptyStatement有效。

为什么不给出错误?

非常简单:如果找到无效语法,则java会出错。但javac是完全有效的语法。相反,如果使用适当的参数启动,empty会发出警告。 full list of warnings that can be dis-/enabled为此目的列出了警告名称-Xlint:all。因此,使用-Xlint:emptyCtrl + Shift + A进行汇编会产生相关警告。

您的IDE也应该有一个选项来启用此类警告。 对于eclipse,请参阅@nullptr's answer。在IntelliJ中,您可以按empty body,在搜索字段中输入if( a() && b() ); 并启用警告(在图像中标记)

IntelliJ enable empty-body warning

这甚至用于什么?

说实话,从简约的角度来看,它没有多大用处。通常有一种方法可以在没有“无所事事”命令的情况下完成任务。无论你喜欢使用

,这都是个人喜好的问题
if( a() ) b();

EmptyStatement

同样适用于使用EmptyStatement的其他情况。关于这个主题的一个重要观点是代码的可读性。在某些情况下,使用no-op可以使代码更具可读性。另一方面,有些情况下使用<ul class="tab_conts" id="recent" style="display: block;"> <li class="tab_cont"> <a href="/test" class="tab_cont_link">Test</a> <a> <desc>Testing</desc> </a> </li> <li class="tab_cont"> <a href="/test" class="tab_cont_link">Test</a> <a> <desc>Testing</desc> </a> </li> </ul> 来理解代码变得非常困难 - 以上示例将计入后来的IMO。

答案 13 :(得分:0)

if中的分号表示java ;中if条件的终止被视为语句的结尾,因此if之后的语句将被执行。

答案 14 :(得分:0)

看这个:

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);不会注意

答案 15 :(得分:0)

我可以想到一个需要空语句的场景(不是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

答案 16 :(得分:0)

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

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

案例2.

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

答案 17 :(得分:-2)

在为我正在使用N by 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之间执行某些操作。

或者,您可以使用异常处理来避免这种语法,但它适用于我的应用程序。