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 == nullobj.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. & 与 && 的核心区别对比

特性 &(位与 / 布尔与) &&(逻辑与)
✅ 操作类型 可用于 intboolean 仅限 boolean
✅ 短路行为 ❌ 不短路,总是计算两边 ✅ 短路,左为 false 时不计算右边
✅ 应用场景 位掩码、标志位操作、非短路布尔判断 条件判断、避免异常(如 NPE)
✅ 性能影响 可能造成不必要的计算或副作用 更安全、更高效

📌 简单粗暴总结:

  • 想做位运算?用 &
  • 想做条件判断?用 &&
  • 想确保两边都执行(比如有副作用的方法调用)?用 &
  • 避免空指针或提升性能?用 &&

5. 总结

  • & 是位运算符,可用于整数的按位与操作,也可用于布尔逻辑(但不短路)
  • && 是逻辑运算符,仅用于布尔表达式,具备短路特性,是日常条件判断的首选
  • 混用两者可能导致性能问题或运行时异常(如 NPE)
  • 在涉及方法调用或可能出错的表达式中,优先使用 &&

搞清楚这两个符号的区别,不仅能写出更安全的代码,也能在 Code Review 时一眼看出潜在问题。别再模糊使用了,该用哪个就用哪个。


原始标题:Bitwise & vs Logical && Operators | Baeldung