如何消灭空指针?

278 阅读2分钟
if( context != null && context.getType() != null){
    //执行某些逻辑。
}

以上我们系统中常见的代码,做了两次非空判断,稍不留神,忘了判断context为空,就会出现空指针异常。空指针的发生是大多因为开发者忘记进行判空,那如何有效避免空指针呢?

拿我们的系统来举例,项目主流程中新增了一个context对象,这个对象某些场景可能为 Null,并且Context中的属性也可能为Null。

为避免潜在的空指针异常,我们打算封装工具方法供开发者使用,无需开发者主动判空,只要使用这个工具方法,就可以安全的访问Context。

Optional 和Lamada判空

于是组里的大神写了一个通用方法,看了几分钟我没明白,用过后真香。

@Nullable
public static <T, R> R getValue(T r, Function<? super T, ? extends R> function) {
   //如果 r = null, 调用map时 会自动返回Null,不会出现空指针
   return Optional.ofNullable(r).map(function).orElse(null);
}

public static <T, R> R valueNotNull(T r, Function<? super T, ? extends R> function) {
   //如果 r = null, 调用map时 会自动返回Null,不会出现空指针
   return Optional.ofNullable(r).map(function).orElse(null) != null;
}

刚才context.getType()判空的代码,使用valueNotNull工具类重写一下。

if(valueNotNull(context, Context::getType)){
    //执行某些逻辑。
}

valueNotNull(Optional.ofNullable(r).map(function).orElse(null)) 做了两个事情

  1. 如果 context为空,那么跳过Map直接返回Null
  2. 如果Context不为空,那么如果执行lamada表达式(Context::getType),如果不存在则为Null,并再次判空。

这样通过工具方法,我们就不会再出现漏写判空语句导致的空指针异常,形成代码CodeReview规范。

三层非空判断

如果有三层费非空判断,则再增加一个lamada表达式、增加一次map()即可。

@Nullable
public static <T, R, E> E valueNotNull(T r, Function<? super T, ? extends R> function,
                                   Function<? super R, ? extends E> function2) {
   //如果 r = null, 调用map时 会自动返回Null,不会出现空指针
   return Optional.ofNullable(r).map(function).map(function2).orElse(null)!=null;
}

//使用Java8 lamada表达式
if(valueNotNull(context, Context::getParam, Param::getType())){
       //执行业务逻辑
}

//原始的方式
if(context!=null && context.getParam()!=null && context.getParam().getType()!=null){
// 执行业务逻辑
}

以上的代码和具体的类无关,如果你的代码中通过多级调用,且每一级都可能为空,可以考虑这个工具类,简化代码设计。

空指针是代码中常出现的异常,有效避免空指针之一就是,基于Lamada表达式,为提供可能为空值字段提供特殊的访问方法。

最后,五阳一直在关注 AI方向,我分享一个对抗AI“一本正经胡说八道”的个人技巧:不要只依赖一个模型。我现在遇到拿不准的信息,会把同一个问题同时扔给2-3个AI(比如千问+DeepSeek),看它们答案的交集。这比单纯选哪个模型更靠谱。想省事的话可以用这个聚合工具一次搞定:AIChatProxy aichatproxy.com

image.png