25

通过“空 if 语句”,我的意思是这样的(注意分号):

if (condition);

我在考虑为此申请时遇到了麻烦。使用 while 循环,您可以执行以下操作:

while (callUntilReturnsFalse());

但是没有这样的 if 语句应用。更重要的是,Java 编译器在遇到这样的语句时不会发出错误或警告。这可能会导致大而无声的问题,尤其是对于冗长而复杂的陈述:

if ((functionA() && functionB(getFoo()) ||
    checkForComplexCondition(arg1, arg2, getBar(getFoo())));
{
    doStuff();
}

我的问题是:为什么在 Java 中允许这样做?而且,更重要的是,我可以启用一个选项以在发生这种情况时发出警告吗?

(这个问题之前被问过关于 C#,它确实发出警告,但我希望找到一种方法来用 Java 引起警告。)

4

9 回答 9

16

为什么在 Java 中允许这样做?

请参阅Java 语言规范(14.6. The Empty Statement)

空语句什么都不做。

它只是被允许的,它相当于(并将被翻译成):

if (condition) {  }

这意味着,如果条件为真,则什么也不做。

如果你使用 eclipse,你可以看看这里,你可能会发现一些有用的东西(我不确定分号终止符是否存在这样的选项):

窗口首选项Java编译器错误/警告

在此处输入图像描述


编辑

正如@nullptr 在他的回答中指出的那样,存在一个 IDE 警告,您需要在Empty statement上设置警告

于 2013-05-07T21:43:25.760 回答
14

我不认为这与问题的意图真正相关,但我认为应该说明它与问题的本质相关。

一个效果:

if(variable);

如果变量是volatile. 它的作用是在当前线程和访问该变量的任何其他线程之间产生一个内存屏障。

public volatile variable;
....
if(variable);

有关更详细的讨论,请参见此处。

我无法想象将这种语句放入您的代码中有任何真正的价值,但我觉得重要的是要注意在这种非常具体的情况下对这种语句有真正的影响。

于 2013-05-07T22:23:21.713 回答
7

有一个我经常使用的结构,“空语句”使我更清楚、更容易理解。这是一个例子:

for (int i=0;  i < argc;  i++)
{
   if (argv[i]=="left")
      hpos++;
   else if (argv[i]=="right")
      hpos--;
   else if (argv[i]=="up")
      ;
   else if (arv[i]=="down")
      ;
   else fprintf(stderr, "Unknown option \"%s\\n".", argv[i]);
}

在这种情况下,我仍然想检查某些选项是否存在,同时只执行其中一些选项的代码。在这种情况下,如上所述,使用 null 语句可以使代码的功能和结构对于必须来维护它的下一个人来说更具可读性和可理解性。

当然有一些方法可以重组此代码以不需要 null 语句。但我不相信它的意图会像代码片段中那样清晰。

于 2013-05-07T22:04:51.807 回答
3

我在 Eclipse 中发现了一个警告Empty statement

例子

感谢 Maroun Maroun 让我走上正轨。

于 2013-05-07T22:07:15.007 回答
2

if我认为空语句的可能性没有那么大的危险。它背后的基本原理在于 Java 语言的语法,它允许空语句;

Block: 
    { BlockStatements }

BlockStatements: 
    { BlockStatement }

BlockStatement:
    LocalVariableDeclarationStatement
    ClassOrInterfaceDeclaration
    [Identifier :] Statement

LocalVariableDeclarationStatement:
    { VariableModifier }  Type VariableDeclarators ;

Statement:
    Block
    ;
    Identifier : Statement
    StatementExpression ;
    if ParExpression Statement [else Statement] 
    assert Expression [: Expression] ;
    switch ParExpression { SwitchBlockStatementGroups } 
    while ParExpression Statement
    do Statement while ParExpression ;
    for ( ForControl ) Statement
    break [Identifier] ;
    continue [Identifier] ;
    return [Expression] ;
    throw Expression ;
    synchronized ParExpression Block
    try Block (Catches | [Catches] Finally)
    try ResourceSpecification Block [Catches] [Finally]

请注意,几乎所有命令式语言都是如此。

我的意思是,如果你忘记了任何实现,那么像其他所有空体一样,找到它可能是危险且难以找到的,当然我不会为此而失眠。在冗长而复杂的语句中,您可能会因为( )关闭错误的表达式对甚至认为您的条件错误(尤其是许多&&and ||)而遇到问题。

于 2013-05-07T21:40:28.827 回答
1

条件可能是具有副作用的函数调用。将其视为错误或警告是不正确的。

于 2013-05-07T21:52:57.880 回答
1

我主要是 C# 开发人员,虽然我有一点 Java 背景。但我认为我的答案适用于两者。我怀疑这不是故意的功能,而是更多的紧急功能。语言的语法(大致)

if (*condition*)
    *statement*

不幸的是,下面的语句都是有效的(我检查过,你可以随意放入 C# 中,编译器不会抱怨):

;

{
}

因此,您突出显示的构造是允许的。

于 2013-05-07T21:41:16.307 回答
0

我相信他们把它留在里面是因为它可以增加代码的可读性。即使不应该对案件采取任何措施,您仍可能希望让人们知道案件很重要。

于 2013-05-07T21:44:13.090 回答
0

在声明中

if  (eval) { //pseudo-code
}

有时数据实际上在评估(eval)时发生了变化。例如,在

while (someIterator.next()) {
}

调用 next() 实际上改变了 someIterator 对象的状态。

当然还有一个典型的例子,它通常是由拼写错误引起的(不推荐)

int x;  
if (x = getNumberOfWidgets() > 5) {
}

传统观点不建议以这种方式编码,因为更难判断发生了什么。但是,这些陈述是合法的,因此这就是允许使用这种“if”陈述的原因之一。

于 2013-05-07T21:43:33.467 回答