Java中的 &= 和 |= 是否支持短路?

43

换句话说,下面这两个语句的行为是否相同?

isFoobared = isFoobared && methodWithSideEffects();
isFoobared &= methodWithSideEffects();

我知道我可以自己编写测试,但有人可能会直接知道答案,而其他人也可能会发现这个答案很有用。

2个回答

49
不,"|="和"&="不会短路,因为它们是"&"和"|"的复合赋值版本,而这两者不会短路。
引用块: JLS 15.26.2 复合赋值运算符 形如"E1 op= E2"的复合赋值表达式等同于"E1 = (T)((E1) op (E2))",其中"T"是"E1"的类型,但"E1"只被计算一次。
因此,假设"boolean &","isFoobared &= methodWithSideEffects()"的等价性为:
isFoobared = isFoobared & methodWithSideEffects(); // no shortcircuit

另一方面,&&||会进行短路计算,但令人费解的是Java没有它们的复合赋值版本。也就是说,Java既没有&&=也没有||=

另请参阅


这个短路业务到底是什么?

boolean逻辑运算符(&|)与它们的条件运算符(&&||)之间的区别在于,前者不会"短路",而后者会。也就是说,在没有异常等情况下:

  • &| 总是评估两个操作数
  • &&|| 有条件地评估右操作数;只有当其值可能影响二元操作的结果时,才会评估右操作数。这意味着当左操作数为以下情况时,不会评估右操作数:
    • &&的左操作数评估为false
      • (因为无论右操作数评估为什么,整个表达式都是false)
    • ||的左操作数评估为true
      • (因为无论右操作数评估为什么,整个表达式都是true)

参考资料


我认为这并不是那么难以理解…事实上,现在我想起来它们几乎完全没有用处。在赋值之后,唯一会改变的值是True和False。这是8个情况中仅有的1种情况,可以让赋值部分有用。在另外7个情况下,结果不需要改变,所以没有必要。当然,|和&符号是有意义的,因为你也可以将它们用于位或/与,从而执行一些有用的操作。 - Wayne Werner
我也认为这是可以解释的。虽然我不能确切地解释它,但我倾向于从右到左阅读赋值语句(先执行这个,然后对那个结果进行某些操作),所以如果左侧的内容会神奇地使右侧不执行,我会非常惊讶。 - Kevin Bourrillion

4
不,它们不会,因为x &= y缩写为x = x&yx |= y缩写为x = x | y。Java没有&&=||=运算符可以实现您想要的功能。 &|运算符(以及~^<<>>>>>)是按位运算符。 对于任何整数类型,表达式x & y将执行按位与操作。 同样,|执行按位或操作。 要执行按位操作,数字中的每个位都被视为布尔值,其中1表示true0表示false。 因此,3 & 2 == 2,因为3在二进制中是0...011,而20...010。 类似地,3 | 2 == 3Wikipedia有一个完整的不错解释不同的运算符。 现在,对于布尔值,我认为您可以使用&|作为非短路&&||的等效项,但无论如何我都想象不出为什么您会想这么做。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接