前言
在
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
进行的优化。