1. 问题引入
之前写过一篇文章 利用JSR303来完成对象参数校验,我们可以很好的对对象进行参数校验。采用这种方法,我们可以对某个对象被使用之前进行必要的参数校验,如果出现异常,我们可以跑出异常也可以返回结果。但是如果我们想对一个方法的参数进行一些类似非空校验的操作,可否有更好的方法来避免产生java.lang.NullPointerException
异常呢?
2. 采用Objects类提供的方法
Objects类是JDK 1.7之后引入的一个Object 工具类,该类主要提个了操作对象的常见的一些方法,例如:
-
public static boolean equals(Object a, Object b)
: 用于比较两个对象是否相等 -
public static boolean deepEquals(Object a, Object b)
:也是用于比较两个对象的,如果是数组的话,将对数组中的每个元素都进行比较 -
public static <T> int compare(T a, T b, Comparator<? super T> c)
:用于两个元素比较的 -
public static <T> T requireNonNull(T obj)
:检测元素是否为null,如果为null,将抛出NullPointerException,否则返回该对象 -
public static <T> T requireNonNull(T obj, String message)
:同样的是检查元素是否为null,如果为null的话,抛出的异常带有message -
public static <T> T requireNonNull(T obj, Supplier<String> messageSupplier)
:也是检查返回值是否为null,如果是的话,将取messageSupplier的中的信息 -
public static boolean isNull(Object obj)
:判断元素是否为null,返回boolean值 -
public static boolean nonNull(Object obj)
:判断元素是否不为null,返回boolean值
其他的还有生成hashCode的一些方法。
下面我们采用其中的requireNonNull
来进行检测
public String testObjects(Object arg){
Object checked= Objects.requireNonNull(arg);
return checked.toString();
}
如果arg为null将会抛出异常
3. 采用Guava提供的Preconditions
Guava提供的Preconditions
中不仅可以对null校验,还有丰富的其他校验方法,我们可以根据Status,State,Index来进行校验
public String testGuava(Object arg){
Object checked= Preconditions.checkNotNull(arg,"%s must not be null",arg);
return checked.toString();
}
如果arg为null的话,将输出以下代码:
Exception in thread "main" java.lang.NullPointerException: arg is marked non-null but is null
at com.liuyao.check.TestNonNull.testLombok(TestNonNull.java:23)
at com.liuyao.check.TestNonNull.main(TestNonNull.java:31)
4. 采用Lombok中的@NonNull注解
Lombok也提供了一个@NonNull
注解在方法的声明中进行校验,例如下面的代码
public String testLombok(@NonNull Object arg){
return arg.toString();
}
Lombok会生成如下代码:
public void testLombok(Object arg) {
if (arg == null) {
throw new NullPointerException("arg is marked @NonNull but is null");
}
arg.toString();
}
5. 采用Checker Framework 中提供的@Nullable和@NonNull
Checker Framework 能够作为 javac
编译器的插件运行,对代码中的数据类型进行检测,预防各类问题。我们可以参照 官方文档,将 Checker Framework 与 maven-compiler-plugin
结合,之后每次执行 mvn compile
时就会进行检查。Checker Framework 的空值检测程序支持几乎所有的注解,包括 JSR 305、Eclipse、甚至 lombok.NonNull
。
例如:
import org.checkerframework.checker.nullness.qual.Nullable;
@Nullable
private Object returnNullable() {
return null;
}
public void testReturnNullable() {
Object obj = returnNullable();
// 错误:obj 可能为空
System.out.println(obj.toString());
}
6. 参考链接
- Lombok features
- Java java.util.Objects类
- Java Objects类
- The Checker Framework
- Java 8 Annotation 新特性在软件质量和开发效率方面的提升