objects.requirenonnullelse在第一个参数为null时返回第二个参数,且不对第二个参数做空检查;它立即求值,无延迟执行,不适用于含副作用或开销大的默认值构造。

Objects.requireNonNullElse 返回 null 时到底用谁?
它不“默认返回”,而是「当第一个参数非 null 就返回它;为 null 才返回第二个参数」——这个逻辑常被误读成“兜底默认值”,但其实 Objects.requireNonNullElse 对第二个参数完全不做空检查,哪怕它是 null,也会原样返回。
常见错误现象:Objects.requireNonNullElse(getUser(), new User()) 看似安全,但如果 getUser() 返回 null,而构造 User() 抛异常,那这行代码就直接崩了——它根本不是“安全创建”,只是条件返回。
- 使用场景:适合两个已知可安全求值的表达式之间做 null fallback,比如缓存未命中时返回另一个缓存变量、配置未设置时回退到常量
- 别把它当
Optional.orElseGet()用:后者延迟执行 Supplier,前者两个参数都会提前求值 - 如果第二个参数是方法调用(如
createDefaultUser()),该方法一定会执行,不管第一个参数是否为 null
和 Objects.requireNonNullElseGet 的关键区别在哪?
requireNonNullElse 是立即求值,requireNonNullElseGet 是懒求值——这是唯一实质差异,但影响巨大。
比如你写 Objects.requireNonNullElse(config.getTimeout(), getDefaultTimeout()),只要 config.getTimeout() 不为 null,getDefaultTimeout() 依然会执行;换成 requireNonNullElseGet 就不会。
立即学习“Java免费学习笔记(深入)”;
- 性能影响:高频调用中,无谓的默认值构造/计算会拖慢吞吐
- 副作用风险:如果
getDefaultTimeout()里有日志、DB 查询或状态变更,用错就触发意外行为 - 兼容性无差别:两者都是 Java 9+ 引入,JDK 8 不支持,别在老项目硬套
为什么不能用 Objects.requireNonNullElse 替代 Optional?
因为它没有链式能力,也不带语义——Optional 表达的是“可能为空的容器”,而 requireNonNullElse 只是一次性三元判断的语法糖。
典型误用:Optional.ofNullable(user).map(User::getName).orElse("N/A") 被强行替换成 Objects.requireNonNullElse(user.getName(), "N/A"),结果 user 为 null 时直接抛 NullPointerException。
- 容易踩的坑:没意识到
requireNonNullElse不处理嵌套 null,它只检查第一个参数本身是不是 null - 替代方案要分层:深层取值必须用
Optional链或 Apache Commons 的ObjectUtils.defaultIfNull+ 安全导航 - 参数类型限制:两个参数必须是同一类型或存在隐式转换,否则编译失败,不像
Optional.orElse支持泛型推导更灵活
简洁写法真能省事?看这几个边界情况
所谓“简洁”,只在非常受限的条件下成立:两个参数都轻量、无副作用、类型一致、且你明确知道第一个参数只可能 null 或有效值。
示例对比:
String name = Objects.requireNonNullElse(user.getName(), "anonymous"); // ❌ user 为 null 时炸
String name = Optional.ofNullable(user).map(User::getName).orElse("anonymous"); // ✅ 安全
- 如果 user 可能为 null,别图省事跳过 Optional 包装
- 字符串拼接类默认值(如
prefix + requireNonNullElse(val, "default"))要注意:若val为 null,prefix + null会变成字符串 "null" - 泛型擦除下,返回值类型靠第一个参数推断,第二个参数若为字面量(如
"abc"),编译器可能推成Serializable & Comparable,引发后续类型不匹配
真正省事的前提,是你已经把 null 的传播路径控制住了;否则,越“简洁”的写法,越容易漏掉一层空指针校验。









