其他答案已经很好地解决了运算符之间的功能差异,但是答案可能适用于当今存在的几乎每种C衍生语言。问题被标记为爪哇,因此我将尽一切努力专门针对Java语言进行回答。
&
并且|
可以是整数位运算符或布尔逻辑算子。按位和逻辑运算符(第15.22节)的语法为:
AndExpression:
EqualityExpression
AndExpression & EqualityExpression
ExclusiveOrExpression:
AndExpression
ExclusiveOrExpression ^ AndExpression
InclusiveOrExpression:
ExclusiveOrExpression
InclusiveOrExpression | ExclusiveOrExpression
的语法EqualityExpression
中定义§15.21,这需要RelationalExpression
在定义§15.20,这又需要ShiftExpression
和ReferenceType
所定义§15.19和§4.3分别。ShiftExpression
要求AdditiveExpression
中所定义§15.18,继续向下钻取,限定基本的算术运算,一元运算符等ReferenceType
深入到所有不同的方式来表示一个类型。(虽然ReferenceType
不包括基本类型,基本类型的定义最终需要的,因为它们可以是用于一个阵列,其尺寸类型是一个ReferenceType
)。
按位和逻辑运算符具有以下属性:
- 这些运算符具有不同的优先级,
&
具有最高优先级和|
最低优先级。
- 这些运算符中的每一个在语法上都是左关联的(每个组从左到右)。
- 如果操作数表达式没有副作用,则每个运算符都是可交换的。
- 每个运算符都是关联的。
- 按位和逻辑运算符可用于比较两个数字类型的操作数或两个类型的操作数
boolean
。所有其他情况都会导致编译时错误。
运算符是按位运算符还是逻辑运算符之间的区别取决于操作数是“可转换为原始整数类型”(第4.2节)还是它们是boolean
或类型Boolean
(第5.1.8节)。
如果操作数是整数类型,则对两个操作数都执行二进制数值提升(第5.6.2节),而将它们都保留为long
s或int
s。操作的类型将是(提升的)操作数的类型。此时,&
将是按位与,^
将是按位异或,并且|
将是按位或。(§15.22.1)
如果操作数为boolean
or Boolean
,则在必要时将对操作数进行拆箱转换(第5.1.8节),并且操作类型为boolean
。&
将导致true
如果两个操作数都是true
,^
将导致true
在两个操作数是不同的,并且|
将导致true
如果操作数是true
。(§15.22.2)
相反, &&
是“ Conditional-And运算符”(第15.23节),||
是“ Conditional-Or运算符”(第15.24节)。它们的语法定义为:
ConditionalAndExpression:
InclusiveOrExpression
ConditionalAndExpression && InclusiveOrExpression
ConditionalOrExpression:
ConditionalAndExpression
ConditionalOrExpression || ConditionalAndExpression
&&
就像一样&
,不同的是它仅在左操作数为时评估右操作数true
。||
就像一样|
,不同的是它仅在左操作数为时评估右操作数false
。
有条件的-并且具有以下属性:
- 条件和运算符在语法上是左关联的(它从左到右分组)。
- 条件和运算符在副作用和结果值方面是完全相关的。也就是说,对于任何表达式
a
,b
和和c
对该表达式的求值都会((a) && (b)) && (c)
产生与该表达式的求值相同的结果,并且以相同的顺序发生相同的副作用(a) && ((b) && (c))
。
- 条件和运算符的每个操作数必须为
boolean
或类型Boolean
,否则会发生编译时错误。
- 条件和表达式的类型始终为
boolean
。
- 在运行时,首先对左侧操作数表达式求值;如果结果具有type
Boolean
,则将其进行拆箱转换(第5.1.8节)。
- 如果结果值为
false
,则条件和表达式的值为,false
并且不计算右侧操作数表达式。
- 如果左侧操作数的值为
true
,则对右侧表达式求值;否则,将求值。如果结果具有type Boolean
,则将其进行拆箱转换(第5.1.8节)。结果值成为条件和表达式的值。
- 因此,
&&
计算相同的结果&
上boolean
的操作数。区别仅在于,右侧操作数表达式是有条件而不是始终进行求值的。
条件-或具有以下属性:
- 条件或运算符在语法上是左联想的(它从左到右分组)。
- 条件或运算符在副作用和结果值方面是完全关联的。也就是说,对于任何表达式
a
,b
和和c
对该表达式的求值都会((a) || (b)) || (c)
产生与该表达式的求值相同的结果,并且以相同的顺序发生相同的副作用(a) || ((b) || (c))
。
- 条件或运算符的每个操作数都必须为
boolean
或类型Boolean
,否则会发生编译时错误。
- 条件或表达式的类型始终为
boolean
。
- 在运行时,首先对左侧操作数表达式求值;如果结果具有type
Boolean
,则将其进行拆箱转换(第5.1.8节)。
- 如果结果值为
true
,则条件或表达式的值为,true
并且不计算右侧操作数表达式。
- 如果左侧操作数的值为
false
,则对右侧表达式求值;否则,将求值。如果结果具有type Boolean
,则将其进行拆箱转换(第5.1.8节)。结果值成为条件或表达式的值。
- 因此,
||
计算与|
on boolean
或Boolean
操作数相同的结果。区别仅在于,右侧操作数表达式是有条件而不是始终进行求值的。
总之,作为@JohnMeagher曾多次在评论中指出,&
和|
,事实上,非短路的操作数是任何的具体情况布尔运算符boolean
或Boolean
。如果采用良好的做法(即没有次要影响),这是一个很小的差异。但是,当操作数不是boolean
s或Boolean
s时,运算符的行为就大不相同了:在Java编程的高级水平上,按位运算和逻辑运算根本无法很好地进行比较。