Java基础之:&和&&及|和||的区别

  相关的运算符(位运算符和逻辑运算符)一共有以下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 ||

 

参考: