【问题标题】:Empty if-statements [duplicate]空的 if 语句 [重复]
【发布时间】:2013-05-08 16:50:13
【问题描述】:

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

if (condition);

我在考虑为此申请时遇到了麻烦。使用 while 循环,您可以这样做:

while (callUntilReturnsFalse());

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

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

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

(这个问题是关于 C# 的 asked before,它确实会发出警告,但我希望找到一种方法来用 Java 引起警告。)

【问题讨论】:

  • @FlorisVelleman 你是什么意思?也许我应该澄清一下,我的意思是完全没有正文的陈述
  • 有一个选项可以让格式将独立的;s 放在自己的行上,这样更容易捕捉。不过,我不确定获得警告的方法。 (我假设我们在谈论日食)
  • 请参阅this question 以获得对该主题的相当全面的处理。归根结底,它是一种有效的(如果无用的话)语言结构。与试图让编译器通知你相比,通过代码格式化找到它会更好。
  • 这不是“无用”。它调用函数。
  • 值得注意的是,如果下一个语句是 else 语句,那么它只会在 condition 为 false 时运行。当然,使用!condition 可以更轻松地编写整个结构。如果您还没有实现“condition 为真”的情况,但仍想编译和运行代码,编译器不给出错误可能很有用。

标签: java language-design


【解决方案1】:

为什么 Java 允许这样做?

Java Language Specification (14.6. The Empty Statement):

空语句什么都不做。

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

if (condition) {  }

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

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

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


编辑

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

【讨论】:

    【解决方案2】:

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

    一个效果:

    if(variable);
    

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

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

    有关更详细的讨论,请参阅here

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

    【讨论】:

      【解决方案3】:

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

      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 语句。但我不相信它的意图会像代码 sn-p 中那样明确。

      【讨论】:

      • 没有考虑到...肯定有更好的方法,但至少我现在知道为什么我的 IDE 说这有时是故意的,而我正在编写一个 if 块(还没有填充它,我读了警告上的工具提示)
      • 我还发现,在某些情况下,为了逻辑清晰,我需要故意使用空语句。但是我不想关闭空语句警告。有没有办法表明这条线是故意的,以便 Eclipse 不发出警告?
      【解决方案4】:

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

      感谢 Maroun Maroun 让我走上正轨。

      【讨论】:

        【解决方案5】:

        我认为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]
        

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

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

        【讨论】:

          【解决方案6】:

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

          if (*condition*)
              *statement*
          

          不幸的是,以下两个语句都是有效的(我检查过,你可以在 C# 中添加任意数量的语句,编译器不会抱怨):

          ;
          
          {
          }
          

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

          【讨论】:

            【解决方案7】:

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

            【讨论】:

              【解决方案8】:

              在声明中

              if  (eval) { //pseudo-code
              }
              

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

              while (someIterator.next()) {
              }
              

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

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

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

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

              【讨论】:

              • 但是说if (eval); 和说eval 有什么不同呢?
              • 在你的 if(eval);例如,它没有什么不同。但是,这并不构成非法声明。但是,在示例 if (evalsToFalse &amp;&amp; evalsToTrue); 中,由于 && 运算符的惰性求值,将不会执行第二次求值。所以在这样的情况下可能会有一些差异。但是在一种语言中做同样的事情通常有不止一种方法——仅仅因为它做同样的事情并不意味着它是非法的(尽管它会使语言更加混乱!)
              【解决方案9】:

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

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2015-02-16
                • 2019-09-14
                • 1970-01-01
                • 1970-01-01
                • 2018-07-22
                相关资源
                最近更新 更多