我使用x!=null以避免NullPointerException。还有其他选择吗?
if (x != null) {
// ...
}
我使用x!=null以避免NullPointerException。还有其他选择吗?
if (x != null) {
// ...
}
当前回答
这是大多数开发人员最常见的错误。
我们有很多方法来处理这个问题。
方法1:
org.apache.commons.lang.Validate //using apache framework
notNull(对象对象,字符串消息)
方法2:
if(someObject!=null){ // simply checking against null
}
方法3:
@isNull @Nullable // using annotation based validation
方法4:
// by writing static method and calling it across whereever we needed to check the validation
static <T> T isNull(someObject e){
if(e == null){
throw new NullPointerException();
}
return e;
}
其他回答
可以在方法调用之前使用拦截器。这就是面向方面编程所关注的。
假设M1(对象测试)是一个方法,M2是一个在方法调用之前应用方面的方法,M2(对象测试2)。如果test2!=null则调用M1,否则执行另一件事。它适用于所有要应用方面的方法。如果要为实例字段和构造函数应用方面,可以使用AspectJ。对于方法方面,Spring也是最佳选择。
你有一个选择
在方法上使用checker框架的@RequiresNonNull。对于ex,如果使用null参数调用一个注释为null的方法,就会得到这个结果。它将在编译期间失败,甚至在代码运行之前!因为在运行时它将是NullPointerException@RequiresNonNull(值={“#1”})静态空隙检查(布尔x){如果(x)System.out.println(“true”);else System.out.println(“false”);}公共静态void main(String[]参数){检查(空);}
得到
[ERROR] found : null
[ERROR] required: @Initialized @NonNull Boolean
[ERROR] -> [Help 1]
还有其他方法,如Use Java 8‘s Optional、Guava Annotations、Null Object pattern等。只要您达到避免的目标,就无所谓了=无效的
通过遵循问题的大多数其他答案,您可以避免很多事情,以避免NullPointerException。我只想添加Java9中引入的其他一些方法,以优雅地处理这种情况,并展示一些旧的方法也可以使用,从而减少您的工作量。
公共静态布尔值isNull(对象obj)如果提供的引用为null,则返回true,否则返回错误。自Java 1.8以来公共静态布尔值nonNull(对象obj)如果提供的引用为非null,则返回true,否则返回错误。自Java 1.8以来公共静态<T>T requireOnNullElse(T对象,T默认对象)如果第一个参数为非null,则返回第一个参数,否则返回非空的第二个参数。自Java 9以来公共静态<T>T requireOnNullElseGet(T obj,供应商<?扩展T>供应商)如果第一个参数为非空,则返回第一个参数,否则返回supplier.get()的非空值。自Java 9以来公共静态<T>T requireOnNull(T obj,供应商<字符串>消息供应商)检查指定的对象引用是否为空,否则将引发自定义的NullPointerException。自Java 1.8以来
有关上述功能的更多详细信息,请参阅此处。
Java8带来了新的Java.util.Optional类,它可以解决一些问题。至少可以说,它提高了代码的可读性,并且在公共API的情况下,使API的契约对客户端开发人员更加清晰。
它们是这样工作的:
给定类型(Fruit)的可选对象被创建为方法的返回类型。它可以是空的或包含Fruit对象:
public static Optional<Fruit> find(String name, List<Fruit> fruits) {
for (Fruit fruit : fruits) {
if (fruit.getName().equals(name)) {
return Optional.of(fruit);
}
}
return Optional.empty();
}
现在看看这段代码,我们在其中搜索给定Fruit实例的Fruit(水果)列表:
Optional<Fruit> found = find("lemon", fruits);
if (found.isPresent()) {
Fruit fruit = found.get();
String name = fruit.getName();
}
您可以使用map()运算符对可选对象执行计算,或从中提取值。orElse()允许您为缺少的值提供回退。
String nameOrNull = find("lemon", fruits)
.map(f -> f.getName())
.orElse("empty-name");
当然,检查空/空值仍然是必要的,但至少开发人员意识到该值可能是空的,忘记检查的风险是有限的。
在从头开始使用Optional构建的API中,只要返回值可能为空,并且仅在不能为空时返回纯对象(惯例),客户端代码可能会放弃对简单对象返回值的空检查。。。
当然,Optional也可以用作方法参数,在某些情况下,可能比5或10个重载方法更好地指示可选参数。
可选提供了其他方便的方法,例如允许使用默认值的orElse,以及与lambda表达式一起使用的ifPresent。
我邀请您阅读这篇文章(我撰写这个答案的主要来源),其中很好地解释了NullPointerException(以及一般的空指针)问题以及Optional带来的(部分)解决方案:Java Optional Objects。
使用Java8,您可以将供应商传递给下面这样的助手方法,
if(CommonUtil.resolve(()-> a.b().c()).isPresent()) {
}
上面的代码替换了下面的锅炉板代码,
if(a!=null && a.b()!=null && a.b().c()!=null) {
}
//通用工具.java
public static <T> Optional<T> resolve(Supplier<T> resolver) {
try {
T result = resolver.get();
return Optional.ofNullable(result);
} catch (NullPointerException var2) {
return Optional.empty();
}
}