前言
在
Java开发中,null就像给黑洞,给错误的排查带来极大的难度,而Guava对null进行了优化,可以方便我们更优雅的处理null。
Optional
Guava中使用Optional来处理null,如使用Optional(null)时,则会快速报错,而使用Java原生方式处理时,则会在具体使用到null时报错,下面通过一个示例说明。
示例
原生Java示例
package com.hust.grid.leesf.optional;
import com.google.common.base.Optional;
public class OptionalTest {
public static void main(String[] args) {
Integer invalidInput = null;
Integer validInput = 10;
sum(invalidInput, validInput);
}
public static int sum(Integer i1, Integer i2) {
return i1 + i2;
}
}
运行结果如下:
Exception in thread “main” java.lang.NullPointerException
at com.hust.grid.leesf.optional.OptionalTest.sum(OptionalTest.java:18)
at com.hust.grid.leesf.optional.OptionalTest.main(OptionalTest.java:10)
可以看到,其会在sum方法中报错,即当运行i1 + i2时报错,若不采取合适的判断非null方法,则该程序会报错。
Guava示例
public class OptionalTest {
public static void main(String[] args) {
Integer invalidInput = null;
Integer validInput = 10;
Optional<Integer> i1 = Optional.of(invalidInput);
Optional<Integer> i2 = Optional.of(validInput);
sum(i1, i2);
//sum1(invalidInput, validInput);
}
public static int sum(Optional<Integer> i1, Optional<Integer> i2) {
return i1.get() + i2.get();
}
运行结果如下:
Exception in thread “main” java.lang.NullPointerException
at com.google.common.base.Preconditions.checkNotNull(Preconditions.java:191)
at com.google.common.base.Optional.of(Optional.java:86)
at com.hust.grid.leesf.optional.OptionalTest.main(OptionalTest.java:10)
可以看到在运行Optional.of(invalidInput)时报错了,不会调用sum方法,使用Optional来规避方法调用时的非null判断,使得能够更快速的抛出异常。
源码分析
创建非null对象
根据
Guava示例,来简单分析Optional的源码,其有Absent和Present两个子类,Absent代表null,Present则代表非null,当调用Optional.of方法时,其会创建Present对象。
Optional.of方法首先调用checkNotNull(reference)方法。当reference为null时,则直接抛出NullPointerException异常,否则创建Present对象。Present对象中有T reference的变量用于保存非null值。
创建null对象
除了创建非
null对象外,还可以特意创建null对象,而创建null对象有两种方法,一种通过fromNullable方法,另一种通过absent方法。
fromNullable方法
可以通过
Optional.fromNullable(null)方法创建,其会创建一个Absent对象表示null,而当调用Optional.fromNullable方法并且传递的参数不为null时,其会正常创建Present对象。
absent方法
直接通过调用
Optional.absent方法即可创建一个Absent对象表示null。
值得注意的是,所有的null对象都为同一个对象(哈希码相同)。
获取元素
上述方法可以通过
Optional来保存传递的变量,再使用时,可调用Optional的get或者or方法获取值。
get方法
对于
Absent对象而言,调用get会抛出异常;对于Present对象而言,调用get会返回reference变量。
or方法
对于
Absent对象而言,调用or会返回传入的参数;对于Present对象而言,调用or会返回原本传入的变量值。
总结
Optional源码比较简单,主要是为了避免运行时null进行的优化。