predicate本身不抛assertionerror,但未判空易引发nullpointerexception;应优先用optional安全链式访问或构造时避免null。

Predicate 本身不抛出断言(assert)异常,但若你在 Predicate 的 test() 方法里写了 assert、或在链式调用中嵌套了可能触发 NPE 的操作(比如 obj.getName().length() > 0),而 obj 为 null,就会直接报 NullPointerException ——这不是断言失败,而是空指针崩溃。关键要分清:是 assert 报 AssertionError,还是未判空导致的 NPE。
先确认是不是真在用 assert
Java 的 assert 默认关闭,除非你加了 -ea 参数启动 JVM。如果没开,所有 assert 都被跳过,根本不会执行,更不会“崩溃”。所以看到运行时报错,大概率是 NPE,不是断言触发的。
检查你的 Predicate 写法,例如:
- ❌ 错误示范(隐含 NPE 风险):
Predicate<user> p = u -> u.getAddress().getCity().startsWith("Sh");</user>
只要 u、u.getAddress() 或 u.getCity() 任一为 null,立刻 NPE。 - ✅ 安全写法(显式判空):
Predicate<user> p = u -> u != null && u.getAddress() != null && u.getAddress().getCity() != null && u.getAddress().getCity().startsWith("Sh");</user>
用 Optional 封装再判断(推荐用于复杂对象链)
对深层嵌套字段,硬写多重判空易出错、难读。可用 Optional 搭配 map 和 filter 实现安全链式访问:
Predicate<user> p = u -> Optional.ofNullable(u) .map(User::getAddress) .map(Address::getCity) .filter(c -> c.startsWith("Sh")) .isPresent();</user>- 优点:逻辑清晰、无 NPE、可读性强;缺点:有轻微对象创建开销,但对绝大多数业务场景可忽略。
统一前置校验 + 自定义工具方法
避免每次手写冗长判空,抽一个工具方法:
static <t> boolean safeCall(Supplier<t> supplier, Predicate<t> condition) { try { return condition.test(supplier.get()); } catch (NullPointerException e) { return false; } }</t></t></t>- 使用:
Predicate<user> p = u -> safeCall(() -> u.getAddress().getCity(), c -> c.startsWith("Sh"));</user> - 注意:这种“捕获 NPE”属于兜底策略,适合临时兼容旧逻辑;长期建议改用 Optional 或重构数据模型。
从源头减少 null(治本之策)
NPE 的根因永远是 null 的传播。与其在 Predicate 里层层防御,不如:
- 构造对象时尽量用非 null 默认值(如空字符串、空集合、Optional.empty());
- DTO/VO 层用 Lombok 的
@NonNull+ 编译期检查,或启用-Xlint:nullable; - API 返回值统一用
Optional<t></t>包装,让调用方明确处理“无值”语义。










