【JAVA8新特性】Optional
这是实习中学到新的类,看业务代码时发现大佬们喜欢用这个类,特别钻研了一下。
- Optional是一个可以为null的容器对象:它可以保存类型T的值,或者仅仅保存null。
- 如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。
- Optional提供很多有用的方法,这样我们就不用显式进行空值检测。
- Optional 类的引入很好的解决空指针异常。
源码分析:
1. 类的结构和构造器
public final class Optional<T> {
// 这个常量为后面调用 empty() 方法时实例化一个Optional对象做准备
private static final Optional<?> EMPTY = new Optional<>();
// 容器内部的值
private final T value;
private Optional() {
this.value = null;
}
private Optional(T value) {
this.value = Objects.requireNonNull(value);
}
// ...
}
2. empty() 方法
该静态方法的泛型T都是由调用该方法的Optional的泛型类型决定,empty()方法其实很简单,将该类的常量EMPTY强制转换为相同类型的Optional对象,而这个empty()方法返回的Optional对象的value值为null。
public static<T> Optional<T> empty() {
@SuppressWarnings("unchecked")
Optional<T> t = (Optional<T>) EMPTY;
return t;
}
测试一下:
public static void main(String[] args){
Optional<Integer> optional = Optional.empty();
Integer i = optional.get();
System.out.println(i);
}
此时会抛异常:java.util.NoSuchElementException: No value present。
原因在于,Optional.empty()后创建的optional的value为null,get()方法的时候会判断value是否为null,如果时null就报错。可以看下一条get()方法的源码。
3. get() / isEmpty() / isPresent() 方法
比较简单,放在一起了。
public T get() {
if (value == null) {
throw new NoSuchElementException("No value present");
}
return value;
}
public boolean isEmpty() {
return value == null;
}
public boolean isPresent() {
return value != null;
}
4. of(T value) / ofNullable(T value) 方法
通过看最开始的源码,可以发现,Optional类将自己的两个构造方法全部私有化,那么肯定会开放公共方法供外部访问。
public static <T> Optional<T> of(T value) {
return new Optional<>(value);
}
public static <T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value);
}
看出区别:ofNullable(T value)创造l时value可以是null,of(T value)的value不能为null。
可以看到new Optional<>(value)的构造函数为:
private Optional(T value) {
this.value = Objects.requireNonNull(value);
}
继续看Objects.requireNonNull(value)的源码:
public static <T> T requireNonNull(T obj) {
if (obj == null)
throw new NullPointerException();
return obj;
}
null时直接抛异常了。
5. ifPresent() / ifPresentOrElse() 方法
简答地说,Consumer类包含一个 accept 抽象方法。该抽象方法对传入的值进行处理,但没有返回值。
- ifPresent():如果value存在就做处理,否则就不处理。
- ifPresentOrElse() 方法:如果value存在就做处理,否则用emptyAction处理。
public void ifPresent(Consumer<? super T> action) {
if (value != null) {
action.accept(value);
}
}
public void ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction) {
if (value != null) {
action.accept(value);
} else {
emptyAction.run();
}
}
6. or() / orElse() / orElseGet() / orElseThrow() 方法
这个方法是用来取值的。
public Optional<T> or(Supplier<? extends Optional<? extends T>> supplier) {
Objects.requireNonNull(supplier);
if (isPresent()) {
return this;
} else {
@SuppressWarnings("unchecked")
Optional<T> r = (Optional<T>) supplier.get();
return Objects.requireNonNull(r);
}
}
public T orElse(T other) {
return value != null ? value : other;
}
public T orElseGet(Supplier<? extends T> supplier) {
return value != null ? value : supplier.get();
}
public T orElseThrow() {
if (value == null) {
throw new NoSuchElementException("No value present");
}
return value;
}
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
if (value != null) {
return value;
} else {
throw exceptionSupplier.get();
}
}
7. filter() 方法
过滤是否符合要求的值。如果value存在,进行过滤。
public Optional<T> filter(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate);
if (!isPresent()) {
return this;
} else {
return predicate.test(value) ? this : empty();
}
}
8. stream() 方法
如果value存在就返回一个仅包含一个value值的stream。
public Stream<T> stream() {
if (!isPresent()) {
return Stream.empty();
} else {
return Stream.of(value);
}
}
看完源码基本就知道如何使用了。之后再更吧。。