【问题标题】:Ternary operator, syntax error when using assignment三元运算符,使用赋值时语法错误
【发布时间】:2013-12-22 09:18:43
【问题描述】:

下面3行代码编译OK。 (请注意,此代码是“人工 Java 编码”的示例,因此不会出现在专业编写的代码中。)

int x, y;
boolean b=true;

x = b ? y=1 : 2;  // Compiles OK.

如果我现在更改上面第 3 行中的代码,使其看起来像下面的代码行,编译器会生成错误。

// Change the position of the "y assignment", and now the code doesn't compile.
x = b ? 1 : y=2;  

这里是语法错误信息:

有人可以解释一下这种行为吗(向 Java 新手学习)?谢谢。

【问题讨论】:

  • 非常有趣。这可能是一个很好的面试问题。
  • 对于任何好奇的人,看起来这两种语法在 C# 中都是有效的。
  • 次要注意:如果b 为真,则y 被赋值为1。但如果b 为假,则不执行此赋值,y 保留其现有值.
  • @Duncan 真的吗?你想在面试时看到这样的问题吗?您是否认为作为 Java 开发人员必须知道 Java 中每个运算符的优先级?您能否告诉我这是否正确编译:if (obj instanceof obj==null ? String.class : Integer.class) 以及它是如何工作的?
  • @Pshemo 我喜欢引发思考和辩论的问题。当然,如果候选人立即知道答案,我会印象深刻,但我没想到会这样。相反,我更愿意看看他们是如何解决问题的;他们有什么想法,看看他们是否有我提供的更多信息。

标签: java ternary-operator


【解决方案1】:

这是因为运算符优先级。第一种情况是这样的:

x = (b ? (y=1) : 2);  // Compiles OK.

而第二个是:

x = (b ? 1 : y) = 2;  

第一个编译确实很好,因为赋值被评估为新值。因此,如果b 为真,则将导致xy 都等于1。第二个就像说:x = 1 = 2。所以,是的,要修复此编译器错误,请在您的语句中添加括号:

x = (b ? 1 : (y = 2));  // Outer () are not needed, but is clearer, IMHO.

更长

首先,operator precedence in Java 表示赋值运算符的优先级低于条件三元运算符。这意味着您的第二个表达式相当于:

x = (b ? 1 : y) = 2;

如您所见,这看起来完全错误。确实,JLS §15.26 是这样说的:

有12个赋值运算符;所有在语法上都是右关联(它们从右到左分组)。因此,a=b=c 表示a=(b=c),它将c 的值分配给b,然后将b 的值分配给a

赋值运算符的第一个操作数的结果必须是变量,否则会发生编译时错误。 (这解释了您面临的编译时错误)

在运行时,赋值表达式的结果是赋值发生后变量的值。赋值表达式的结果本身并不是一个变量。

应用右关联性:

x = ((b ? 1 : y) = 2);

最后我们可以看到为什么这会产生编译器错误:三元条件运算符的结果是不是变量(据我所知,它实际上不在JLS中,但是编译器在这样一个简单的测试用例中告诉你:https://ideone.com/kMr7Xv)。

【讨论】:

  • @guido 您认为哪个表达是正确的? x = (b ? (y=1) : 2); 不是这样。
  • @Duncan:我不知道发生了什么。这可能是 StackOverflow 中的一个错误。我们对此评论的回复被自动删除。 Guido 删除了他的声明,但自动回来了......在我的评论中,我加入了这个演示:ideone.com/X3ezxq
  • @Martijn Corteaux 我确实删除了我的答案(因为你的答案先来了几分钟,答案更好);我的评论还在,但它是错误的
  • @MartijnCourteaux 矩阵中的一个小故障。
【解决方案2】:

兄弟,试着把表达式放在括号里。

X= (b?1 : (y=2));

这会很好。

【讨论】:

    【解决方案3】:

    Java运算符优先级如下

    http://docs.oracle.com/javase/tutorial/java/nutsandbolts/operators.html

    这里ternary 出现在assignment 操作之前。所以你的陈述会是这样的

    x= (三元求值)=赋值

    如果您仍想为 y 设置值,当 b 为 false 时,您可以使用 () for 'y=2' 引入三元评估。

    x = b ? 1 : (y=2);
    

    【讨论】:

      【解决方案4】:

      请参阅“Java 运算符优先级”。 同时,使用:

      x = (b ? 1 : (y=2)); 
      

      【讨论】:

        猜你喜欢
        • 2012-02-14
        • 2012-11-19
        • 2012-10-01
        • 2013-06-28
        • 1970-01-01
        • 1970-01-01
        • 2011-07-02
        • 2021-04-29
        • 2021-11-23
        相关资源
        最近更新 更多