Optional
Optional是JDK1.8提供的一个新类,希望可以通过该类的引入解决令人厌烦的null判断问题,非常好用。这个类是一个包装类,将要操作的Java been封装到该类的对象里面,同时将一些常用的判断逻辑封装为成员方法,结合lambda表达式,实现比较优雅的链式调用。
API类型 | 说明 | 方法 |
---|---|---|
构造API | 构建一个Optional对象 | empty()、of()、ofNullable() |
获取API | 获取Optional对象里包装的值 | get()、orElse()、orElseGet()、orElseThrow() |
转换API | 将Optional对象里包装的值转换成一个新的值 | map()、faltMap() |
判断API | 将Optional对象里包装的值做逻辑判断 | filter()、isPresent()、ifPresent() |
一、构建API
- Optional(T value)
Optional(T value)为构造函数,他是private
权限的,不为外部调用。
/**
* Constructs an instance with the described value.
*
* @param value the non-{@code null} value to describe
* @throws NullPointerException if value is {@code null}
*/
private Optional(T value) {
this.value = Objects.requireNonNull(value);
}
- empty()
Optional类内部还维护一个value为null的对象,大概就是长下面这样的:
public final class Optional<T> {
//省略....
private static final Optional<?> EMPTY = new Optional<>();
private Optional() {
this.value = null;
}
//省略...
public static<T> Optional<T> empty() {
@SuppressWarnings("unchecked")
Optional<T> t = (Optional<T>) EMPTY;
return t;
}
}
empty() 的作用就是返回EMPTY对象
- of(T value)
public static <T> Optional<T> of(T value) {
return new Optional<>(value);
}
of(T value)函数内部调用了构造函数。根据构造函数的源码我们可以得出两个结论:
- 通过of(T value)函数所构造出的Optional对象,当Value值为空时,依然会报NullPointerException。
- 通过of(T value)函数所构造出的Optional对象,当Value值不为空时,能正常构造Optional对象。
使用场景:
当我们在运行过程中,不想隐藏NullPointerException。而是要立即报告,这种情况下就用Of函数。
- ofNullable(T value)
public static <T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value);
}
相比较of(T value)的区别就是:
当value值为null时,of(T value)会报NullPointerException异常;ofNullable(T value)不会throw Exception,ofNullable(T value)直接返回一个EMPTY对象。
二、获取API
- orElse(T other)和orElseGet(Supplier other)
/**
* Return the value if present, otherwise return {@code other}.
*
* @param other the value to be returned if there is no value present, may
* be null
* @return the value, if present, otherwise {@code other}
*/
public T orElse(T other) {
return value != null ? value : other;
}
/**
* Return the value if present, otherwise invoke {@code other} and return
* the result of that invocation.
*
* @param other a {@code Supplier} whose result is returned if no value
* is present
* @return the value if present otherwise the result of {@code other.get()}
* @throws NullPointerException if value is not present and {@code other} is
* null
*/
public T orElseGet(Supplier<? extends T> other) {
return value != null ? value : other.get();
}
orElse和orElseGet的用法如下所示,相当于value值为null时,给予一个默认值。
- orElseThrow(Supplier exceptionSupplier)
orElseThrow,就是value值为null时,直接抛一个异常出去:
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
if (value != null) {
return value;
} else {
throw exceptionSupplier.get();
}
}
三、转换API
map(Function mapper)和flatMap(Function> mapper)
两个函数做的是转换值的操作:
public final class Optional<T> {
//省略....
public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else {
return Optional.ofNullable(mapper.apply(value));
}
}
//省略...
public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else {
return Objects.requireNonNull(mapper.apply(value));
}
}
}
这两个函数,在函数体上没什么区别。唯一区别的就是入参。
map函数所接受的入参类型为Function<? super T, ? extends U>,
而flapMap的入参类型为Function<? super T, Optional<U>>。
四、判断API
-
filter(Predicate predicate)
filter 方法接受一个 Predicate 来对 Optional 中包含的值进行过滤,如果包含的值满足条件,那么还是返回这个 Optional;否则返回 Optional.empty。 -
isPresent()和ifPresent(Consumer consumer)
这两个函数放在一起记忆,isPresent即判断value值是否为空,而ifPresent就是在value值不为空时,做一些操作。