27

最近我看到一个使用这个的代码:

boolean val = something();
val |= somethingElse();

有趣的部分是在布尔原始类型上创建的 |=(类似二进制)运算符。

令我惊讶的是 |= 存在于布尔值,就好像它是整数类型一样,并在 Java 规范中搜索了这个运算符,但找不到任何东西。

如果左值已经为真,我会很好奇是否评估右操作数。

有人可以指出我的Java规范吗?

4

5 回答 5

35

来自 JLS:

15.26.2。复合赋值运算符

形式的复合赋值表达式E1 op= E2等价于E1 = (T) ((E1) op (E2)),其中T是 的类型E1,除了E1只计算一次。

15.22.2。布尔逻辑运算符&, ^, 和|

当 a &, ^, or|运算符的两个操作数都是booleanorBoolean类型时,按位运算符表达式的类型是boolean。在所有情况下,操作数都会根据需要进行拆箱转换(第 5.1.8 节)。

对于|,如果两个操作数值都为假,则结果值为假;否则,结果为真。

这意味着

val |= somethingElse();

严格等价于

val = val | somethingElse();

(假设somethingElse()返回booleanBoolean)。

如果左值已经为真,我会很好奇是否评估右操作数。

是的,它会被评估,因为|不会短路:

15.7.2. 操作前评估操作数

Java 编程语言保证在执行操作本身的任何部分之前,运算符的每个操作数(条件运算符 、 和 除外&&||似乎? :都已被完全评估。

15.24。条件或运算符||

因此,计算与on或操作数||相同的结果。它的不同之处仅在于右手操作数表达式是有条件地计算而不是总是计算。|booleanBoolean

于 2013-03-14T13:55:03.147 回答
4

有关. _ _ |有关. _ _ |=这些定义正是您的想法。

令我惊讶的是缺少||=操作员。

于 2013-03-14T13:57:11.050 回答
3

按位逻辑运算符将具有与布尔值上的“普通”逻辑运算符相同的效果。

来自Java 语言规范15.22:

当 &、^ 或 | 的两个操作数 运算符的类型为 boolean 或 Boolean,则按位运算符表达式的类型为 boolean。在所有情况下,操作数都会根据需要进行拆箱转换(第 5.1.8 节)。

对于 &,如果两个操作数值都为真,则结果值为真;否则,结果为假。

对于 ^,如果操作数的值不同,则结果值为真;否则,结果为假。

对于 |,如果两个操作数的值都为假,则结果值为假;否则,结果为真。

唯一真正的区别是按位运算符不能用于短路评估。

例如,此代码将抛出NullPointerException

Boolean b1 = new Boolean(true);
Boolean b2 = null;
if (b1 || b2) {
    //no null pointer here;
}
if (b1 | b2) {
    //null pointer here;
}
于 2013-03-14T13:54:10.663 回答
2
>>I'd be curious if right operand is evaluated if left value already is true.

位运算符(如|, &, ..)在完成之前评估双方。

在某些情况下,逻辑运算符(如&&, ||, ..)可以跳过第二部分的评估。这被称为short-circuit

于 2013-03-14T14:01:57.700 回答
-1

它不是二进制的,它是“或”逻辑语句的意思

 val |= {something else} 

与布尔表达式相同:

val == val or {something else} 

这是包容性的或(数学表达式和计算机科学中的常规或使用)

在某些编程语言中或被两个 || 标志和一些由一个| 其中之一是 SQL 和我所知道的 DTD JSON 等所有数据库语言。

于 2013-03-14T16:47:54.060 回答