【问题标题】:Using conditional operator without assigning its outcome使用条件运算符而不分配其结果
【发布时间】:2011-01-15 18:59:01
【问题描述】:

为什么我必须将以下条件表达式的结果分配给变量才能编译?

piece.isWhite() ? whitePieceSquares.add(getSquare(pos)) : blackPieceSquares.add(getSquare(pos));

上面不编译,下面可以:

boolean garbage = piece.isWhite() ? whitePieceSquares.add(getSquare(pos)) : blackPieceSquares.add(getSquare(pos));

List#add() 返回一个布尔值,但我会忽略它。仅仅是条件运算符被设计成需要对函数返回的值进行赋值,并且返回的函数必须具有相同的类型吗?

【问题讨论】:

  • “它不解析”是指“它不编译”吗?还有,isWhite()的返回类型是什么?
  • 好的,好的。它无法编译,因为它没有正确解析。我很高兴我们解决了这个问题。这会让任何试图阅读它的人感到困惑。
  • 而 isWhite 是一个布尔值(显然是因为它可以编译)。编辑您的评论以假装您在发表有用的评论的方式。
  • "编辑您的评论以假装您在发表有用的评论的方式。" -- 这会激励其他人提供帮助。
  • @schnozzinkobenstein:讽刺会让你一事无成。您向我们寻求帮助。我试图让其他试图帮助的人更清楚地了解这个问题。此外,如果isWhite() 返回一个整数(1 或 0),则第二个版本将编译。

标签: java conditional-operator


【解决方案1】:

来自section 14.8 of the JLS(表达式语句):

某些类型的表达式可以用分号作为语句:

ExpressionStatement:
      StatementExpression ;

StatementExpression:
       Assignment
       PreIncrementExpression
       PreDecrementExpression
       PostIncrementExpression
       PostDecrementExpression
       MethodInvocation
       ClassInstanceCreationExpression

通过计算表达式来执行表达式语句;如果表达式有值,则丢弃该值。当且仅当表达式的计算正常完成时,表达式语句的执行才能正常完成。

与 C 和 C++ 不同,Java 编程语言只允许将某些形式的表达式用作表达式语句。

...

另一方面,该语言允许在表达式语句中使用所有最有用的表达式,并且不需要将方法调用用作表达式语句来调用 void 方法,因此几乎不需要这种技巧。如果需要技巧,可以使用赋值语句(第 15.26 节)或局部变量声明语句(第 14.4 节)。

基本上,条件运算符的原则目标是评估其操作数 - 您将其用于副作用。

Peter Lawrey 的回答显示了一个更好的用途 - 您使用条件运算符来计算出将块添加到哪个方格,然后调用该方法。

【讨论】:

  • 那么 Peter Lawrey 的代码版本是否正确使用,或者如果我使用它,我仍然只是将它用于副作用?
  • 我想我还是不太明白。我是否应该只在需要时才使用它:someVariable=conditional-operator?
  • @schnozzinkobenstein:Peter 的回答是一个完全合理的使用 - 条件表达式本身可能没有 副作用,但您使用的是 result 作为副作用方法的目标。就个人而言,我可能会使用局部变量而不是直接在表达式的结果上调用方法,但它们在逻辑上是相同的。
【解决方案2】:

试试

(piece.isWhite() ? whitePieceSquares : blackPieceSquares).add(getSquare(pos));

编辑:不知道为什么有人怀疑这是一个有效的陈述。这是一个较短的示例,您应该能够编译/运行它。

boolean out = true;
(out ? System.out : System.err).println("Hello");

【讨论】:

  • 也不是声明。也不是1+1;我认为 John Skeet 提出了规范的相关部分; ExpressionStatements 的特殊类,不必将其值分配给变量。
  • 是什么让你认为它不是一个声明?
  • 不,这工作得很好,因为表达式中的最外层是一个方法调用,因此它可以是一个语句。但是 ?: 本身不能。
  • 我认为这是有效的,因为您实际上使用了 ?: 表达式的返回值。
【解决方案3】:

在 C 中,这是可能的,因为你可以写类似的东西

void foo(int bar) {
    bar;
}

在 java 中,你不能,我也不会错过它。然而,如果你出于某种原因不喜欢写 if ... else ...,这应该可以编译:

(piece.isWhite() ? whitePieceSquares : blackPieceSquares).add(getSquare(pos));

【讨论】:

  • 感谢您的反对,但为什么呢?测试了 Java 和 C,都可以编译。
  • @extraneon - 这是合法的,应该可以在 Java 中完美编译
  • 你是对的。您正在使用使其成为有效表达式的返回值。我会尽快更新投票。
【解决方案4】:

基本上答案是:只是因为。 ?: 和所有算术运算符只能出现在表达式的右侧。

【讨论】:

    【解决方案5】:

    我猜你的add 函数返回一个布尔值。那些必须去某个地方,不是吗?

    【讨论】:

    • 不,你可以扔掉任何表达式的返回值。
    • 我的帖子说 add 函数返回一个布尔值,所以你不必猜测。
    • 如果add被定义为返回void,它仍然没有编译。
    猜你喜欢
    • 2012-12-05
    • 2013-12-01
    • 2018-11-04
    • 2011-02-06
    • 1970-01-01
    • 2023-03-26
    • 2018-06-15
    • 2014-06-13
    • 2012-07-03
    相关资源
    最近更新 更多