绝大多数布尔条件判断必须用 && 而不是 &,因其提供短路求值,可防止空指针、跳过无效耗时操作;& 仅适用于位运算或需强制执行右侧副作用的极少数场景。

什么时候用 && 而不是 &?
绝大多数布尔条件判断场景,必须用 &&。它不是“可选优化”,而是防止空指针、NPE 和非法状态的核心手段。
- 如果左边是
null检查,右边是方法调用(如obj.getName()),用&会直接触发NullPointerException - 如果左边是权限校验(
user.hasRole("ADMIN")),右边是耗时操作(loadSensitiveData()),用&会导致无意义执行 -
&&在第一个false出现时立即停住;&会硬算完所有布尔子表达式——哪怕结果早已注定
& 真的只能用于位运算?
不完全是。但作为逻辑运算符使用 & 是危险且罕见的,只在两种明确场景下合理:
- 你需要强制执行右侧副作用:比如
logAttempt() & validateInput(),要求日志一定写入,不管校验是否通过 - 两个布尔表达式完全独立、无依赖、无异常风险,且你明确放弃短路收益(例如单元测试中模拟固定求值顺序)
- 更常见的是它作为位运算符出现:
flags & 0x04判断第 3 位是否开启,这时左右都是整数,&天然按位工作,和逻辑无关
性能差异到底有多大?
不是“快一点”,而是“避免执行”。差异不在纳秒级运算本身,而在跳过整个右侧表达式带来的开销节省。
- 右侧是数据库查询?
&&下user != null && user.loadProfile()中,null时根本不会发 SQL - 右侧是文件 IO 或远程调用?
&会照常打开连接、序列化、等待超时 - JIT 编译器不会帮你把
&优化成&&——语义不同,编译器必须严格遵守求值规则
一个真实踩坑案例:用 & 替代 && 导致定时任务失败
某服务用 task.isReady() & task.execute() 控制任务流转。上线后发现部分任务反复失败,日志显示 execute() 报了 IllegalStateException,但 isReady() 明明返回 false。
立即学习“Java免费学习笔记(深入)”;
- 问题根源:
&强制执行了execute(),哪怕前置检查失败 - 修复方式:仅改一个字符 →
task.isReady() && task.execute(),失败任务不再误触发 - 额外教训:IDE 默认不警告这种替换,静态检查工具(如 SpotBugs)才可能捕获
&在布尔上下文中的误用
短路不是语法糖,是 Java 布尔求值模型的刚性约定。一旦混用 & 和 &&,出问题往往不是“结果不对”,而是“不该跑的代码跑了”——这种错误很难复现,也最难调试。











