1. 概述
在 Java 中,我们有两种方式表达“与”操作:&
和 &&
。它们看起来相似,行为却大不相同。你有没有在代码里不小心混用过?结果可能让你踩坑。
本文将深入剖析 &
与 &&
的核心区别,带你搞懂位运算、短路机制等关键概念。别再模糊使用了,看完这篇你就明白了。
2. 位运算符 & 的使用
&
是位运算中的“按位与”操作符,它会对两个整数的每一位二进制位进行比较:只有当两个对应位都为 1 时,结果位才为 1,否则为 0。
举个例子:
int six = 6;
int five = 5;
我们对它们执行 &
操作:
int resultShouldBeFour = six & five;
assertEquals(4, resultShouldBeFour);
为什么结果是 4?来看它们的二进制表示:
Binary of decimal 4: 0100
Binary of decimal 5: 0101
Binary of decimal 6: 0110
执行按位与运算:
0110 (6)
& 0101 (5)
------
0100 (4)
✅ 结果 0100
转换为十进制就是 4。
完整测试代码如下:
int six = 6;
int five = 5;
int resultShouldBeFour = six & five;
assertEquals(4, resultShouldBeFour);
2.1 & 在布尔类型中的使用
⚠️ 注意:&
也可以用于布尔值运算。虽然它本质是位运算符,但在布尔上下文中,它的行为类似于逻辑“与”——**只有两个操作数都为 true
时,结果才是 true
**。
示例:
boolean trueBool = true;
boolean anotherTrueBool = true;
boolean falseBool = false;
boolean trueANDtrue = trueBool & anotherTrueBool; // true
boolean trueANDFalse = trueBool & falseBool; // false
测试验证:
assertTrue(trueANDtrue);
assertFalse(trueANDFalse);
❌ 踩坑提醒:即使用于布尔运算,&
依然不会短路,它会完整计算左右两边的表达式。这一点和 &&
截然不同,后面会重点讲。
3. 逻辑运算符 && 的使用
&&
是逻辑“与”操作符,专门用于布尔表达式。它也遵循“全真为真”的规则:只有两个操作数都为 true
时,结果才是 true
。
继续用上面的变量:
boolean trueBool = true;
boolean anotherTrueBool = true;
boolean falseBool = false;
boolean anotherFalseBool = false;
boolean trueANDtrue = trueBool && anotherTrueBool; // true
boolean trueANDFalse = trueBool && falseBool; // false
boolean falseANDFalse = falseBool && anotherFalseBool; // false
验证结果:
assertTrue(trueANDtrue);
assertFalse(trueANDFalse);
assertFalse(falseANDFalse);
3.1 短路机制(Short-circuit)
✅ &&
最关键的特性是短路求值:如果左侧表达式为 false
,则直接跳过右侧表达式的计算,整个表达式结果为 false
。
这在实际开发中非常有用,比如避免空指针:
if (obj != null && obj.isValid()) {
// 只有 obj 不为 null 时,才会调用 isValid()
}
如果这里用 &
,即使 obj == null
,obj.isValid()
依然会被执行,直接抛出 NullPointerException
。
来看一个简单示例:
boolean shortCircuitResult = (2 < 1) && (4 < 5);
assertFalse(shortCircuitResult);
✅ 实际执行中,(4 < 5)
根本不会被计算,因为左侧 (2 < 1)
已经是 false
。
3.2 && 不能用于整数类型
⚠️ 重要限制:&&
只能用于布尔类型。如果你尝试用它操作整数,编译器会直接报错:
int five = 2;
int six = 4;
int result = five && six; // ❌ 编译错误!Operator '&&' cannot be applied to 'int', 'int'
而 &
则可以同时用于整数(位运算)和布尔(逻辑与),但语义完全不同。
4. & 与 && 的核心区别对比
特性 | & (位与 / 布尔与) |
&& (逻辑与) |
---|---|---|
✅ 操作类型 | 可用于 int 、boolean 等 |
仅限 boolean |
✅ 短路行为 | ❌ 不短路,总是计算两边 | ✅ 短路,左为 false 时不计算右边 |
✅ 应用场景 | 位掩码、标志位操作、非短路布尔判断 | 条件判断、避免异常(如 NPE) |
✅ 性能影响 | 可能造成不必要的计算或副作用 | 更安全、更高效 |
📌 简单粗暴总结:
- 想做位运算?用
&
- 想做条件判断?用
&&
- 想确保两边都执行(比如有副作用的方法调用)?用
&
- 想避免空指针或提升性能?用
&&
5. 总结
&
是位运算符,可用于整数的按位与操作,也可用于布尔逻辑(但不短路)&&
是逻辑运算符,仅用于布尔表达式,具备短路特性,是日常条件判断的首选- 混用两者可能导致性能问题或运行时异常(如 NPE)
- 在涉及方法调用或可能出错的表达式中,优先使用
&&
搞清楚这两个符号的区别,不仅能写出更安全的代码,也能在 Code Review 时一眼看出潜在问题。别再模糊使用了,该用哪个就用哪个。