如何用Java核心代码替代Guava的MoreObjects.firstNonNull且不破坏逻辑?
替换Guava MoreObjects.firstNonNull的Java核心实现
Guava的MoreObjects.firstNonNull有两个核心行为必须严格保留:
- 短路求值:优先返回第一个非null参数,且仅当第一个参数为null时才会计算第二个参数
- 非空校验:若两个参数均为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
相关产品推荐
相关产品推荐

