【问题标题】:Replacing an if statement with a disjunction用析取替换 if 语句
【发布时间】:2014-03-12 08:43:26
【问题描述】:

只是为了好玩,我试图替换:

if (set1.add(x) == false)
{
    set2.add(x);
}

与:

set1.add(x) || set2.add(x);

但是,Eclipse 抱怨:

Syntax error on token "||", invalid AssignmentOperator
The left-hand side of an assignment must be a variable

谁能对这些错误消息有所了解?它们对我没有多大意义。

【问题讨论】:

  • 正如它所说的;它需要类似于:boolean temp = set1.add(x) || set2.add(x);.
  • set1.add(x) ? false : set2.add(x) 怎么样? (还没有尝试过,Java 规则有时很模糊,所以我并不是说它会更好。)
  • +1 用于发现这种奇怪现象。顺便说一句,bool foo(){return true;} bool bar(){return true;} int main(){ foo() || bar(); return 0;} 是有效的 C 和 C++。所以肯定是 JLS 语法有什么奇怪的地方或者是编译错误。
  • @vefthym 问题标题使 OP 的意图非常清楚恕我直言。
  • @Bathsheba 这是 C/C++ 语法和 Java 之间的区别。 JLS 明确指出;在 Java 中,并不是每个表达式都可以用作语句。我在my answer 中包含了引用。

标签: java grammar boolean-logic short-circuiting


【解决方案1】:

正如@qqilihq 在 cmets 中所说的那样尝试做

boolean temp = set1.add(x) || set2.add(x);

或者更尴尬:

if(set1.add(x) || set2.add(x));

【讨论】:

  • 我不认为 OP 要求解决方案修复,而是假设 Java 语法不允许该构造。请注意,等效语法在 C 和 C++ 中有效。
【解决方案2】:

根据文档,可以以分号结尾的 java 语句是:

Assignment expressions
Any use of ++ or --
Method invocations
Object creation expressions

你写的不是statement,而是expressionHere 你可以找到更多关于语句和表达式的信息。如此简单但值得一看。

【讨论】:

    【解决方案3】:

    声明

    boolean temp = set1.add(x) || set2.add(x);
    

    任何变体都是危险的。你几乎永远不会知道那里会发生什么。请注意,如果第一个表达式是true,则不会评估正确的表达式。也就是说,只有当它尚未包含在 set1 中时,才会尝试将其添加到 set2。

    编辑:现在,再次阅读问题,看来这正是您想要的。所以我认为 Mustafa Genç 的 anser https://stackoverflow.com/a/21755051 在这里是相关的

    通常情况下,你应该把你想做的事情写清楚

    boolean wasNotContainedInSet1 = set1.add(x);    
    boolean wasNotContainedInSet2 = set2.add(x);    
    boolean wasNotContainedInAnySet = 
        wasNotContainedInSet1 | wasNotContainedInSet2;
    

    boolean wasNotContainedInSet1 = set1.add(x);    
    if (!wasNotContainedInSet1) {
        set2.add(x);    
    }
    

    或者其他...

    【讨论】:

    • 如果set2 已经包含在set2 中,则不添加x 正是我想要的:)
    • @FredOverflow 是的,抱歉,您可能已经看到了“编辑”——我很晚才意识到这是您的实际意图,这或多或少是一个“学术”问题。 Mustafa Genç 和 Joshua Taylor 解释说,实际的问题是,set1.add(x) || set2.add(x) 的尝试是这不是一个声明。
    【解决方案4】:

    我只想:

    if (!set1.add(x))
        set2.add(x);
    

    【讨论】:

      【解决方案5】:

      到目前为止有很多答案,但我同意Bohemian's answer 最直接的简化(虽然它不使用||)是这样的:

      if ( !set1.add(x) ) set2.add(x);
      

      但这并不能解释错误消息。 Mustafa Genç comes closer on this,但我认为看看这里的语言规范是值得的。 exp1 || exp2 是一个表达式,这里的问题是您试图在需要语句的上下文中使用它。根据14.8. Expression Statements,某些类型的表达式可以通过附加分号用于预期语句:

      14.8. Expression Statements

      某些类型的表达式可以用作语句,如下所示 他们用分号。

      ExpressionStatement:
          StatementExpression ;
      
      StatementExpression:
          Assignment
          PreIncrementExpression
          PreDecrementExpression
          PostIncrementExpression
          PostDecrementExpression
          MethodInvocation
          ClassInstanceCreationExpression
      

      表达式语句通过计算表达式来执行;如果 表达式有值,该值被丢弃。

      但是,您不能做您想做的事情的原因是,并非每个表达式都可以用作语句。但是,它确实讨论了一些解决此问题的方法。来自规范的同一部分(强调添加):

      与 C 和 C++ 不同,Java 编程语言只允许某些 要用作表达式语句的表达式形式。注意 Java 编程语言不允许“强制转换为 void” - void 不是类型 - 所以写表达式的传统 C 技巧 声明如:

      (void)... ;  // incorrect!
      

      不起作用。另一方面,Java 编程语言允许所有最有用的表达式 在表达式语句中,它不需要方法调用 用作表达式语句来调用 void 方法,所以这样的 几乎从不需要技巧。 如果需要技巧,要么 赋值语句(§15.26)或局部变量声明 可以改为使用语句(第 14.4 节)。

      Reik Val's answer 中的第一个片段正在使用这种方法:

      boolean temp = set1.add(x) || set2.add(x);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-11-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-08-03
        相关资源
        最近更新 更多