最近我看到了使用此代码的代码:
boolean val = something();
val |= somethingElse();
有趣的部分是| =(二进制)运算符在布尔基元类型上生成。
让我感到惊讶的是,布尔值存在| =,就好像它是整数类型一样,并搜索了该运算符的Java规范,但找不到。
如果左值已经为真,我会好奇是否评估右操作数。
有人能指出我的Java规范吗?
答案 0 :(得分:30)
来自JLS:
15.26.2. Compound Assignment Operators
E1 op= E2
形式的复合赋值表达式等同于E1 = (T) ((E1) op (E2))
,其中T
是E1
的类型,但E1
仅被评估一次。15.22.2. Boolean Logical Operators
&
,^
, and|
当
&
,^
或|
运算符的两个操作数都是boolean
或Boolean
类型时,则按位运算符表达式的类型是boolean
。在所有情况下,操作数都必须根据需要进行拆箱转换(第5.1.8节)。对于
|
,如果两个操作数值都为false,则结果值为false;否则,结果是真的。
这意味着
val |= somethingElse();
严格等同于
val = val | somethingElse();
(假设somethingElse()
返回boolean
或Boolean
)。
如果左值已经为真,我会好奇是否评估右操作数。
是的,它会被评估,因为|
不会短路:
15.7.2. Evaluate Operands before Operation
Java编程语言保证运算符的每个操作数(条件运算符
&&
,||
和? :
除外)在操作本身的任何部分之前都得到完全评估执行。15.24. Conditional-Or Operator
||
因此,
||
计算与|
或boolean
个操作数上的Boolean
相同的结果。它的不同之处仅在于有条件地而不是总是评估右侧操作数表达式。
答案 1 :(得分:4)
有关|
的定义,请参阅http://docs.oracle.com/javase/specs/jls/se5.0/html/expressions.html#15.22.2。有关|=
的定义,请参阅http://docs.oracle.com/javase/specs/jls/se5.0/html/expressions.html#15.26.2。这些定义正是您的想法。
令我惊讶的是缺少||=
运营商。
答案 2 :(得分:2)
按位逻辑运算符对布尔值的“普通”逻辑运算符具有相同的效果。
来自Java Language Specification 15.22:
当&,^或|的两个操作数时运算符的类型为boolean或 布尔值,然后按位运算符表达式的类型是布尔值。 在所有情况下,操作数都要进行拆箱转换(第5.1.8节) 必要时。
对于&amp ;,如果两个操作数值都为真,则结果值为true; 否则,结果是错误的。
对于^,如果操作数值不同,则结果值为true; 否则,结果是错误的。
对于|,如果两个操作数值都为false,则结果值为false; 否则,结果是真的。
唯一真正的区别是按位运算符不能用于短路评估。
例如,此代码将抛出NullPointerException
:
Boolean b1 = new Boolean(true);
Boolean b2 = null;
if (b1 || b2) {
//no null pointer here;
}
if (b1 | b2) {
//null pointer here;
}
答案 3 :(得分:2)
>>I'd be curious if right operand is evaluated if left value already is true.
按位运算符(如|
,&
,..)在完成之前评估双方。
在某些情况下,逻辑运算符(如&&
,||
,..)可以跳过对第二部分的评估。这称为short-circuit
。
答案 4 :(得分:0)
它不是二进制,它是“OR”逻辑语句意味着
val |= {something else}
与布尔表达式相同:
val == val or {something else}
包含或(常规或用于数学表达和计算机科学)
在某些编程语言中或由两个编程语言注明||标志和一些一个|其中一个是SQL和我所知道的DTD JSON等所有数据库语言。