使用Optional处理NullPointerException

一、 Java中的null

在java中,使用null表示引用的默认值(null是Java中的关键字)。引用在声明的时候不指向任何实例,此时值为null。

1
2
3
Object o1; // null
Object o2 = null; // null
Object o3 = new Object(); // not null

除此之外,在找不到对应资源的时候,除了抛异常,还可能返回null

例如在java.util.HashMap#get中,

1
2
3
4
5
// 在没有输入key对应的value时,返回null
public V get(Object key) {
Node<K,V> e;
return (e = getNode(hash(key), key)) == null ? null : e.value;
}

了解更多

关于null的更多信息:Java中有关Null的9件事

综上几点,可以说null无处不在,因此导致到处需要判空操作 or 处理空指针异常(NullPointerException)。

二、 Optional是怎样处理null值的?

业务中,我们可能有这样的场景:
一个Map:

1
2
3
4
Map<String, Object> subMap = new HashMap<>();
subMap.put("subkey", "subValue");
Map<String, Map> map = new HashMap<>();
map.put("key", subMap);

然后获取嵌套Map中的某个值:

1
2
3
4
5
6
7
8
9
10
11
Object res = null;
if (map.containsKey("key")) {
Map valueMap = map.get("key");
if (valueMap.containsKey("subkey")) {
res = valueMap.get("subkey");
}
}
if (res == null) {
res = "Empty";
}
System.out.println(res);

Or

1
2
3
4
5
try {
res = map.get("key").get("subkey");
} catch (Exception e) {
res = "Empty";
}

总是不如Groovy等一些编程语言自带的安全的属性/方法访问操作符。

user?.getUsername()?.toUpperCase();

使用Optional处理NullPointerException,可以达到类似的效果:

1
2
3
4
5
6
Object res = optional.map(o -> o.get("key"))
.map(o -> {
Map omap = ((Map) o);
return omap.get("subkey");
}).orElse("Empty");
System.out.println(res);

到此为止,最有用的特性之一已经讲完了。

三、 Optional其他方法

Optional全部方法

java.util.Optional#map之外,还有java.util.Optional#flatMap