这篇文章主要介绍了Java中避免空指针异常的方法,本文讨论Optional类型、Objects类等技术,需要的朋友可以参考下
没人会喜欢空指针异常!有什么方法可以避免它们吗?或许吧。。
本文将讨论到以下几种技术
1.Optional类型(Java 8中新引入的)
2.Objects类(Java 7中原有的)
Java 8中的Optional类
它是什么?
1.Java 8中新引入的类型
2.它是作为某个指定类型的对象的包装器或者用于那些不存在对象(null)的场景
简单来说,它是处理空值的一个更好的替代品(警告:乍一看可能并没有那么明显)
基本用法
它是一种类型(一个类)——那么,怎么才能创建一个这个类型的实例?
使用下它的三个静态方法就可以了:
public static Optional
return Optional.of(input);
}
public static Optional
if (!new Random().nextBoolean()) {
input = null;
}
return Optional.ofNullable(input);
}
public static Optional
return Optional.empty();
}
好吧,那如何去消费/使用Optional呢?
public static void consumingOptional() {
Optional
if (wrapped.isPresent()) {
System.out.println(“Got string – ” + wrapped.get());
}
else {
System.out.println(“Gotcha !”);
}
}
public static void consumingNullableOptional() {
String input = null;
if (new Random().nextBoolean()) {
input = “iCanBeNull”;
}
Optional
System.out.println(wrapped.orElse(“default”));
}
public static void consumingEmptyOptional() {
String input = null;
if (new Random().nextBoolean()) {
input = “iCanBeNull”;
}
Optional
System.out.println(wrapped.orElseGet(
() -> {
return “defaultBySupplier”;
}
));
}
不论如何,这两个方法明显的区别就在于它们的参数——你可以选择使用lambda表达式而不是Supplier的实例来完成这个(一个函数式接口)
为什么使用Optional要比常见的null检查强?
1.使用Optional最大的好处就是可以更明白地表述你的意图——返回null值的话会让消费者感到疑惑(当真的出现NPE的时候)这是不是故意返回的,因此还得查看javadoc来进一步定位。而使用Optional就相当明了了。
2.有了Optional你就可以彻底避免NPE了——如上所提,使用Optional.ofNullable,orElse以及orElseGet可以让我们远离NPE。
另一个救星!
看下这个代码片段
package com.abhirockzz.wordpress.npesaviors;
import java.util.Map;
import java.util.Objects;
public class UsingObjects {
String getVal(Map
return aMap.containsKey(key) ? aMap.get(key) : null;
}
public static void main(String[] args) {
UsingObjects obj = new UsingObjects();
obj.getVal(null, “dummy”);
}
}
1.Map对象
2.进行搜索使用的key
3.方法调用的这个实例
如果抛出NPE的话,我们怎么能确定到底是哪个是null的?
package com.abhirockzz.wordpress.npesaviors;
import java.util.Map;
import java.util.Objects;
public class UsingObjects {
String getValSafe(Map
Map
“Map is null”);
String safeKey = Objects.requireNonNull(key, “Key is null”);
return safeMap.containsKey(safeKey) ? safeMap.get(safeKey) : null;
}
public static void main(String[] args) {
UsingObjects obj = new UsingObjects();
obj.getValSafe(null, “dummy”);
}
}
1.如果对象不为null的话就返回它本身
2.如果值为null的话,返回的NPE会带有指定的消息
为什么比if(myObj!=null)要好?
你所看到的栈跟踪信息会很清楚地看见Objects.requireNonNull的方法调用。这个再配合你自己的错误日志,可以让你更快地定位问题。。。至少在我看来是更快。
你还可以自己自义校验器,比如说实现一个简单的校验器来确保没有空值。
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.function.Predicate;
public class RandomGist {
public static
Objects.requireNonNull(object);
Objects.requireNonNull(predicate);
if (predicate.test(object)){
throw new IllegalArgumentException(msgToCaller);
}
return object;
}
public static void main(String[] args) {
//Usage 1: an empty string (intentional)
String s = “”;
System.out.println(requireNonEmpty(Objects.requireNonNull(s), (s1) -> s1.isEmpty() , “My String is Empty!”));
//Usage 2: an empty List (intentional)
List list = Collections.emptyList();
System.out.println(requireNonEmpty(Objects.requireNonNull(list), (l) -> l.isEmpty(), “List is Empty!”).size());
//Usage 3: an empty User (intentional)
User user = new User(“”);
System.out.println(requireNonEmpty(Objects.requireNonNull(user), (u) -> u.getName().isEmpty(), “User is Empty!”));
}
private static class User {
private String name;
public User(String name){
this.name = name;
}
public String getName(){
return name;
}
}
}