Java8 Optional用法详解
起因
Optional字面上意思是可选择的,主要是java新增用来防止空异常的类,Optional是容器类,存储单元素,通过这个类来包装对象来简化对被包装对象的判空、取值操作。
Optional类可以帮助简化判空但是还是无法避免NPE,需要我们提升自身对代码空值的敏感度。
Optional基本方法
1.两种方式的静态构造方法。
第一种不可传入空值,传入空值会报NPE。
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);
}
2.isPresent
判断Optional内对象是否为空。不为空返回true,为空返回false。
public boolean isPresent() {
return value != null;
}
判断Optional容器内对象,有值就执行Consumer函数,否则什么都不做。
public void ifPresent(Consumer<? super T> consumer) {
if (value != null)
consumer.accept(value);
}
3.get
获取容器内对象的值。如果为空,则抛出NoSuchElementException异常。
public T get() {
if (value == null) {
throw new NoSuchElementException("No value present");
}
return value;
}
4.filter
过滤方法,一般用于判断容器中的值是否与预测的值一样,有值就执行Predicate函数,Predicate返回true,返回当前对象,否则返回EMPTY对象。没值返回自身对象。
public Optional<T> filter(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate);
if (!isPresent())
return this;
else
return predicate.test(value) ? this : empty();
}
5.map
映射的意思,判断当前容器中对象是否为空,如果为空返回EMPTY,否则就返回包装了Function函数返回结果的容器类Optional。
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));
}
}
6.flatMap
与上面的方法相似只不过在Function函数中需要自己将对象封装到Optional。
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));
}
}
7.orElse
获取容器中的对象。判断容器中对象是否为空,不为空返回对象,否则返回默认值。
public T orElse(T other) {
return value != null ? value : other;
}
8.orElseGet
获取容器中的对象。判断容器中对象是否为空,不为空返回对象,否则返回Supplier函数返回的值。
public T orElseGet(Supplier<? extends T> other) {
return value != null ? value : other.get();
}
9.orElseThrow
获取容器中的对象。判断容器中对象是否为空,不为空返回对象,否则抛出Supplier函数返回的异常。
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
if (value != null) {
return value;
} else {
throw exceptionSupplier.get();
}
}
核心用法
1.尽量少用isPresent
与get
方法,多使用orElse
、orElseGet
和orElseThrow
简化if判断。
使用Optional前
if (null != father) {
return father;
} else {
return new Father();
}
使用Optional改写后
return Optional.ofNullable(father).orElseGet(Father::new);
2.根据具体场景,多使用map
来简化开发。
使用Optional前
if(user != null) {
String name = user.getUsername();
if(name != null) {
return name.toUpperCase();
} else {
return null;
}
} else {
return null;
}
使用Optional后
return user.map(User::getUsername).map(String::toUpperCase).orElse(null);
又或者是这样
if (father == null || father.getName == null) {
Value = father.getName;
} else {
value = "DEFAULT";
}
使用Optional后
value = Optional.ofNullable(father).map(Father::getName).orGet("DEFAULT");
参考资料
jdk8 Optional类源码