相关的运算符(位运算符和逻辑运算符)一共有以下2类:
- & 、| 、~ 、^ ( &= 、|= 、ˆ=)
-
- & , ^ 和 |
-
-
- 作用范围:既可以当作整数位运算符(char/short/int/long或者对应包装类,短类型的会扩展提升到int,且结果是int/long),也可以当作布尔逻辑运算符(true/false或者对应包装类,结果也是布尔类型)
- 优先级:& > ^ > |,各个操作符在语法上都是从左到右
- 整数位运算符
-
-
-
-
- & 是按位与:bit位都是1时该bit位结果为1,其他的都为0
- ^ 是按位异或:bit位不同时该bit位结果为1,其他的都为0
- | 是按位或:bit位都是0时该bit位结果为0,其他的都为1
-
-
-
- 布尔逻辑运算符
-
-
-
- & 与运算:都为true时结果才为true,否则结果都是false
- ^ 异或运算:都不同时结果为true,否则结果都是false
- | 或运算:都是false则结果时false,否则结果都是true
- 都没有短路作用,前后的表达式(若是)都需要运算
-
-
- ~ :按位取反的一元运算符
-
-
- 只作用于整数,且至少会提升至int
- ~x = (-x)-1 恒成立
-
- 条件逻辑运算符:&&、|| 和 !
-
- 条件逻辑与运算符 && :
-
-
- 只做布尔逻辑与操作,操作数只能是布尔值或其包装类,结果也是布尔型
- 和 & 类似,从左到右执行,但只有在左边的表达式为true时才会计算右边的,即遇上第一个false就停止并返回false(短路与)。只有当所有表达式都是true时才返回true
- 因此,&& 计算的结果与 & 对布尔操作数的结果相同,不同之处在于&&是按条件计算,第一个false之后的条件都不会执行(无副作用),而 & 则总是计算
-
- 条件逻辑或运算符 || :
-
-
- 只做布尔逻辑或操作,操作数只能是布尔值或其包装类,结果也是布尔型
- 和 | 类似,从左到右执行,但只有在左边的表达式为false时才会计算右边的,即遇上第一个true就停止并返回true(短路或)。只有当所有表达式都是false时才返回false
- 因此,|| 计算的结果与 | 对布尔操作数的结果相同,不同之处在于||是按条件计算,第一个true之后的条件都不会执行(且无副作用),而 | 则总是计算
-
- 条件逻辑非运算符 ! :
-
-
- 一元运算符,其实就是对true/false取反,就只有这两,取反就是非此即彼。
-
注:以上说明基本来自于Java语言规范,具体参考后面的相关链接。
&和&&、|和||的区别总结如下:
- 相同点:都可以用于布尔逻辑运算,最终的表达式结果是一样的
- 不同点:
-
- && 和 || 称为条件布尔运算符,只能用于布尔运算,而 & 和 | 不仅是布尔逻辑运算符,而且还可以用于整数位运算。
- && 有短路与的作用(Short-circuit evaluation,短路求值,也有提到 lazy evaluation),是逐个条件判断、带条件结束的,即遇到第一个为false时即刻返回false(已得到整个条件判断的结果为false),后面的表达式(如有)不再执行(因此不会有更多副作用),而 & 会将所有表达式都执行判断(eager evaluation)
- || 有短路或的作用,同样也是逐个条件判断、带条件结束的,即遇到第一个为true时即刻返回true(已得到整个条件判断的结果为true),后面的表达式(如有)不再执行(因此不会有更多副作用),而 | 会将所有表达式都执行判断(eager evaluation)
- 项目使用中,如果仅仅只是条件判断(绝大多数场景),建议使用 && 和 || ,尽早结束判断,也不会让后续的表达式执行产生更多的副作用;如果需要所有表达式都执行(可能涉及到/用到相关表达式的副作用),则使用 & 和 | 。
- 笔者注:条件运算,主要是看成不成立,需不需要依赖其他条件来抉择,[7]What is the difference between & and && in Java? 中提到的一个概念 dependent condition。如果能决定结果,后面的就不会再进一步执行了。布尔逻辑,则是所有表达式的一个总逻辑。对Short-circuit evaluation有兴趣可自行进一步探索 [8]Differences in boolean operators: & vs && and | vs || 。
参考:
- [1]15.22.1. Integer Bitwise Operators &, ^, and | https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.22.1
- [2]15.22.2. Boolean Logical Operators &, ^, and | https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.22.2
- [3]15.15.5. Bitwise Complement Operator ~ https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.15.5
- [4]15.23. Conditional-And Operator && https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.23
- [5]15.24. Conditional-Or Operator || https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.24
- [6]15.15.6. Logical Complement Operator ! https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.15.6
- [7]What is the difference between & and && in Java? https://stackoverflow.com/questions/5564410/what-is-the-difference-between-and-in-java
- [8]Differences in boolean operators: & vs && and | vs || https://stackoverflow.com/questions/4014535/differences-in-boolean-operators-vs-and-vs
- [9]Why do we usually use || over |? What is the difference? https://stackoverflow.com/questions/7101992/why-do-we-usually-use-over-what-is-the-difference