Java中用&&和||做空指针防御的核心是利用短路特性:&&将判空放左侧、操作放右侧以避免NPE;||用于布尔逻辑兜底,不可直接替代空合并;复杂场景推荐Optional封装短路逻辑。

Java 中用短路逻辑运算符(&& 和 ||)做空指针防御,核心是利用“左操作数为 false 时不计算右操作数”的特性,把判空放在左边,把可能触发 NPE 的操作放在右边。
用 && 防御调用方法或访问属性前的空指针
当需要在对象非空的前提下调用其方法或访问字段时,把 obj != null 放在 && 左侧,后续操作放右侧。只要左侧为 false,右侧根本不会执行,自然避开 NPE。
-
✅ 安全写法:
if (user != null && user.isActive()) { ... } -
❌ 危险写法:
if (user.isActive() && user != null) { ... }—— 若user为null,先调用isActive()就抛异常 - 同理适用于链式调用场景:
if (order != null && order.getCustomer() != null && order.getCustomer().getEmail() != null) { ... }
用 || 提供默认值避免空引用参与运算
当某个变量可能为 null,但后续要用它做比较、拼接或传参时,可用 || 快速兜底。注意:必须配合布尔表达式,且左侧为 false(如 null 在布尔上下文中为 false)才触发右侧。
-
✅ 常见用法(需配合三元或赋值):
String name = (user == null) ? "Anonymous" : user.getName();—— 这是更清晰的写法 -
⚠️ 注意:
||本身不能直接“替换 null”,但可结合布尔逻辑简化判断,例如:if (user == null || !user.hasPermission("edit")) { throw new AccessDeniedException(); } - 不推荐用
||做非布尔类型的“空合并”,比如userName || "guest"在 Java 中不合法(那是 JavaScript 写法),Java 应用Objects.requireNonNullElse(user.getName(), "guest")或三元操作符
与 Optional 配合提升可读性与安全性
短路运算符适合简单条件判断,但嵌套多层判空会降低可读性。此时可升级为 Optional,它本质也依赖短路思想(map、filter 等操作在空值时自动跳过)。
立即学习“Java免费学习笔记(深入)”;
-
✅ 更健壮的链式安全访问:
Optional.ofNullable(user).map(User::getProfile).map(Profile::getAvatarUrl).orElse("/default.png"); -
✅ 替代 if 判空逻辑:
Optional.ofNullable(config).filter(c -> c.isValid()).ifPresent(this::applyConfig); - 短路逻辑是底层机制,
Optional是对它的封装和语义强化,两者不冲突,可组合使用
注意事项与常见误区
短路不是万能的,用错位置或忽略副作用仍会导致问题。
-
❌ 方法有副作用时慎用:
if (isValid() && saveToDB()) { ... }—— 若isValid()返回false,saveToDB()不执行,这可能是预期;但如果业务要求“无论是否有效都保存”,就不能依赖短路 -
❌ 混淆
&&和&:&是位运算/非短路逻辑运算符,即使左侧为false,右侧仍会执行,可能导致 NPE -
✅ 推荐习惯:所有涉及对象方法调用前,先显式判空并置于
&&左侧;复杂对象图访问优先考虑Optional或工具类如 Apache Commons Lang 的ObjectUtils.defaultIfNull


















