You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Java核心代码替代Guava的MoreObjects.firstNonNull且不破坏逻辑?

替换Guava MoreObjects.firstNonNull的Java核心实现

Guava的MoreObjects.firstNonNull有两个核心行为必须严格保留:

  1. 短路求值:优先返回第一个非null参数,且仅当第一个参数为null时才会计算第二个参数
  2. 非空校验:若两个参数均为null,抛出NullPointerException

以下是两种完全兼容原逻辑的替代方案:


方案1:自定义工具方法(推荐,复用性强)

实现一个和Guava逻辑完全对齐的通用工具方法,原有代码只需替换类名即可:

// 放到项目通用工具类中,比如ObjectUtils.java
public final class ObjectUtils {
    private ObjectUtils() {} // 禁止实例化

    public static <T> T firstNonNull(T first, T second) {
        if (first != null) {
            return first;
        }
        if (second != null) {
            return second;
        }
        throw new NullPointerException("Both parameters are null");
    }
}

替换调用代码:

// 替换Guava的import为自定义工具类
import com.yourcompany.utils.ObjectUtils;

// 调用逻辑完全不变,仅替换类名
Profile recipientProfile =
        ObjectUtils.firstNonNull(credit.getRecipientProfile(), credit.getRecipientBusinessProfile());

方案2:内联实现(适合单场景使用)

如果仅在当前代码块使用,可以用Optional链式调用实现,既保证短路求值,又保留全null抛NPE的逻辑:

Profile recipientProfile = Optional.ofNullable(credit.getRecipientProfile())
        .orElseGet(() -> Optional.ofNullable(credit.getRecipientBusinessProfile())
                .orElseThrow(() -> new NullPointerException("Both parameters are null")));

或者用三元运算符+显式空校验(注意必须加空校验,否则会丢失原逻辑的异常抛出行为):

Profile recipientProfile = credit.getRecipientProfile() != null 
        ? credit.getRecipientProfile() 
        : credit.getRecipientBusinessProfile();

// 必须添加此行,确保和原逻辑一致:全null时抛出NPE
if (recipientProfile == null) {
    throw new NullPointerException("Both parameters are null");
}

重要提醒

  • 绝对不能仅用三元运算符而不加空校验:这会导致两个参数均为null时返回null,而非抛出NPE,直接破坏原有业务逻辑
  • 所有方案都严格保证短路求值:不会在第一个参数非null时调用第二个参数的get方法,避免不必要的数据库查询或方法调用

内容的提问来源于stack exchange,提问作者Peter Penzov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 06:43:19