其他答案很好地涵盖了运算符之间的函数差异,但这些答案可以适用于目前存在的几乎每一种c派生语言。这个问题带有java的标签,因此我将努力具体地、从技术上回答java语言。
&和|可以是整数位运算符,也可以是布尔逻辑运算符。按位运算符和逻辑运算符(§15.22)的语法是:
AndExpression:
EqualityExpression
AndExpression & EqualityExpression
ExclusiveOrExpression:
AndExpression
ExclusiveOrExpression ^ AndExpression
InclusiveOrExpression:
ExclusiveOrExpression
InclusiveOrExpression | ExclusiveOrExpression
The syntax for EqualityExpression is defined in §15.21, which requires RelationalExpression defined in §15.20, which in turn requires ShiftExpression and ReferenceType defined in §15.19 and §4.3, respectively. ShiftExpression requires AdditiveExpression defined in §15.18, which continues to drill down, defining the basic arithmetic, unary operators, etc. ReferenceType drills down into all the various ways to represent a type. (While ReferenceType does not include the primitive types, the definition of primitive types is ultimately required, as they may be the dimension type for an array, which is a ReferenceType.)
位运算符和逻辑运算符具有以下属性:
这些运算符具有不同的优先级,&具有最高优先级,|具有最低优先级。
这些操作符在语法上都是左关联的(每个组从左到右)。
如果操作数表达式没有副作用,每个操作符都是可交换的。
每个运算符都是结合的。
位运算符和逻辑运算符可用于比较数值类型的两个操作数或布尔类型的两个操作数。所有其他情况都会导致编译时错误。
操作符是位操作符还是逻辑操作符的区别取决于操作数是“可转换为基本整型”(§4.2)还是boolean或boolean类型(§5.1.8)。
如果操作数是整型,则对两个操作数执行二进制数字提升(§5.6.2),将它们都保留为长型或整型。操作的类型将是(提升的)操作数的类型。此时,&将是按位与,^将是按位异或,|将是按位异或。(§15.22.1)
如果操作数是布尔型或布尔型,操作数将在必要时进行开箱转换(§5.1.8),操作类型将为布尔型。如果两个操作数都为真,&将返回真;如果两个操作数不同,^将返回真;如果其中一个操作数为真,|将返回真。(§15.22.2)
相反,&&是“条件与操作符”(§15.23),||是“条件与操作符”(§15.24)。它们的语法定义为:
ConditionalAndExpression:
InclusiveOrExpression
ConditionalAndExpression && InclusiveOrExpression
ConditionalOrExpression:
ConditionalAndExpression
ConditionalOrExpression || ConditionalAndExpression
&&类似于&,除了它只在左操作数为真时计算右操作数。||类似于|,除了它只在左操作数为false时计算右操作数。
条件-并且具有以下属性:
The conditional-and operator is syntactically left-associative (it groups left-to-right).
The conditional-and operator is fully associative with respect to both side effects and result value. That is, for any expressions a, b, and c, evaluation of the expression ((a) && (b)) && (c) produces the same result, with the same side effects occurring in the same order, as evaluation of the expression (a) && ((b) && (c)).
Each operand of the conditional-and operator must be of type boolean or Boolean, or a compile-time error occurs.
The type of a conditional-and expression is always boolean.
At run time, the left-hand operand expression is evaluated first; if the result has type Boolean, it is subjected to unboxing conversion (§5.1.8).
If the resulting value is false, the value of the conditional-and expression is false and the right-hand operand expression is not evaluated.
If the value of the left-hand operand is true, then the right-hand expression is evaluated; if the result has type Boolean, it is subjected to unboxing conversion (§5.1.8). The resulting value becomes the value of the conditional-and expression.
Thus, && computes the same result as & on boolean operands. It differs only in that the right-hand operand expression is evaluated conditionally rather than always.
条件-或具有以下属性:
The conditional-or operator is syntactically left-associative (it groups left-to-right).
The conditional-or operator is fully associative with respect to both side effects and result value. That is, for any expressions a, b, and c, evaluation of the expression ((a) || (b)) || (c) produces the same result, with the same side effects occurring in the same order, as evaluation of the expression (a) || ((b) || (c)).
Each operand of the conditional-or operator must be of type boolean or Boolean, or a compile-time error occurs.
The type of a conditional-or expression is always boolean.
At run time, the left-hand operand expression is evaluated first; if the result has type Boolean, it is subjected to unboxing conversion (§5.1.8).
If the resulting value is true, the value of the conditional-or expression is true and the right-hand operand expression is not evaluated.
If the value of the left-hand operand is false, then the right-hand expression is evaluated; if the result has type Boolean, it is subjected to unboxing conversion (§5.1.8). The resulting value becomes the value of the conditional-or expression.
Thus, || computes the same result as | on boolean or Boolean operands. It differs only in that the right-hand operand expression is evaluated conditionally rather than always.
简而言之,正如@JohnMeagher在评论中反复指出的那样,&和|实际上在操作数为布尔或布尔的特定情况下是非短路布尔操作符。通过良好的实践(即:没有次要影响),这是一个微小的差异。然而,当操作数不是布尔值或布尔值时,操作符的行为就大不相同了:位操作和逻辑操作在Java编程的高层中根本无法进行比较。