听到同事们说Optional类是Java1.8新增的类可以用来判断对象是否为null。当时感到一丝丝疑问:为了判null至于新出一个类吗?直到了学习了官方文档和实际演示了一遍,发现Optional并不是只是判null这么简单。
Java1.8发布了十来年,实际也使用了四五年,今天才开始正式学习新增的特新之一。实在汗颜。废话不多说了,来看看Optional类是如何处理对象为空的情况。
一、简单应用
来看下常规是的示例:
List<String> list = null;
if(null != list){
list.forEach((String a )->System.out.println(a));
}
通常情况下,当接收的对象可能存在null时,我们可能会增加一层判空条件来避免万恶的空指针。
而Optional给我们又提供了一种的新的处理方式:通过增加一个默认的返回对象,来避免空指针。
List<String> list = null;
Optional.ofNullable(list).orElse(Arrays.asList("1","2","3")).forEach((String a )->System.out.println(a));
通过调用Optional类的ofNullable和orElse方法就规避了空指针的情况。
那Optional类是如何解决的这种情况,看下Optional的源码:
/**
* Returns an {@code Optional} describing the specified value, if non-null,
* otherwise returns an empty {@code Optional}.
*
* @param <T> the class of the value
* @param value the possibly-null value to describe
* @return an {@code Optional} with a present value if the specified value
* is non-null, otherwise an empty {@code Optional}
*/
public static <T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value);
}
/**
* Returns an empty {@code Optional} instance. No value is present for this
* Optional.
*
* @apiNote Though it may be tempting to do so, avoid testing if an object
* is empty by comparing with {@code ==} against instances returned by
* {@code Option.empty()}. There is no guarantee that it is a singleton.
* Instead, use {@link #isPresent()}.
*
* @param <T> Type of the non-existent value
* @return an empty {@code Optional}
*/
public static<T> Optional<T> empty() {
@SuppressWarnings("unchecked")
Optional<T> t = (Optional<T>) EMPTY;
return t;
}
/**
* 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;
}
从源码中看出ofNullable(T value)方式的Optional提供的静态方法,当value不为null将返回指定value类型的Optional对象,如果为空则返回一个没有指定类型的Optional对。
orElse(T other)是Optional提供的成员方法,意在提供另一种选择,当other不为null则直接返回other,如果传入的是null,则返回的也是null。
以上是关于对Optional的初探。而当注意到源码的方法不止两个时,可能也会对这个类其他方法有兴趣去一探究竟。
二、简单分析Optional类的API
先看下具体的都有哪些方法
(1)类的属性:从Optional类并不复杂,类本身被final修饰不能被继承,同时构造方法私有化,通过new的方式肯定是实现不了。但是Optional类提供了三个可创建Optional对象的静态方法。
ofNullable(T value)
of(T value)
两个方法类似,但是最大的区别是当入参为null时of依然会报空指针异常,而ofNullable会返回一个没有指定类型的Optional对象,empty()方法显而易见只是创建了一个没有指定类型的Optional对象。在开发过程中ofNullable应该会是首选。
public final class Optional<T> {
//构造方法
private Optional() {
this.value = null;
}
private Optional(T value) {
this.value = Objects.requireNonNull(value);
}
//静态方法
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);
}
public static<T> Optional<T> empty() {
@SuppressWarnings("unchecked")
Optional<T> t = (Optional<T>) EMPTY;
return t;
}
(2)成员方法:
isPresent();
get();
ifPresent(Consumer<? super T> consumer);
isPresent()和get()这个两个成员方法是关于值的判断:isPresent判断Optional是否已经被实例化,如果不为null可以配合get()方法获取指定类型;ifPresen可以通过函数Consumer对指定类型对象进程处理。
//源码1
public boolean isPresent() {
return value != null;
}
public T get() {
if (value == null) {
throw new NoSuchElementException("No value present");
}
return value;
}
//源码2
public void ifPresent(Consumer<? super T> consumer) {
if (value != null)
consumer.accept(value);
}
//示例1
Optional<List<String>> optionalStringList = Optional.ofNullable(new ArrayList<>());
if(optionalStringList.isPresent()){
List<String> list = optionalStringList.get();
}
}
//示例2
Optional<List<String>> optionalStringList =
Optional.ofNullable(Arrays.asList("1","2","3"));
optionalStringList.ifPresent( list -> list.forEach((String a )->System.out.println(a)));
map(Function<? super T, ? extends U> mapper);
flatMap(Function<? super T, Optional<U>> mapper);
这两个实例方法依然可以通过函数对指定类型处理,两个方法区别是 map(Function<? super T, ? extends U> mapper)方法可以返回其他指定的类型的Optional,也就是你给了我什么,我不一定还给你什么。而flatMap(Function<? super T, Optional<U>> mapper)应为做了限定,所以也就是你给什么我就还给你什么。
//源码
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));
}
}
//示例
List list = new ArrayList();
list.add("1");
Optional<List<String>> optionalStringList = Optional.ofNullable(list);
Optional<List<String>> optionalStringList1 = optionalStringList.flatMap(list2 -> {
list2.add("4");
return optionalStringList;
});
List<String> strings1 = optionalStringList.get();
//示例
Optional<List<String>> optionalStringList2 = Optional.ofNullable(Arrays.asList("1", "2", "3"));
Optional<HashMap<String, String>> stringStringHashMap = optionalStringList2.map(list3 -> {
HashMap<String, String> map = new HashMap<>();
for (int i = 0; i < list3.size(); i++) {
map.put(list3.get(i), String.valueOf(i));
}
return map;
});
HashMap<String, String> stringStringHashMap1 = stringStringHashMap.get();
orElse(T other)当指定返回类型为空时,返回入参指定类型为orhter的Optional对象
orElseGet(Supplier<? extends T> other) 使用函数Supplier 返回指定类型的具体对象,如果指定类型为空,则返回other指定类型对象。
orElseThrow(Supplier<? extends X> exceptionSupplier) 返回自定义异常
//源码
public T orElse(T other) {
return value != null ? value : other;
}
//示例:
List<String> strings = Optional.ofNullable(Arrays.asList("1")).orElse(new ArrayList<>());
//源码
public T orElseGet(Supplier<? extends T> other) {
return value != null ? value : other.get();
}
//示例
Optional<List<String>> optionalStringList2 = Optional.ofNullable(Arrays.asList("4","5","6"));
Optional<List<String>> optionalStringList = Optional.ofNullable(Arrays.asList("1","2","3")).orElseGet(() -> {
return optionalStringList2.get()
});
//源码
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws
{
if (value != null) {
return value;
} else {
throw exceptionSupplier.get();
}
}
//示例
Optional.ofNullable(null).orElseThrow(() -> new Exception("值为空"));
filter(Predicate<? super T> predicate) 使用函数Predicat的拦截器,如果存在一个值,并且该值与给定谓词匹配。
public Optional<T> filter(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate);
if (!isPresent())
return this;
else
return predicate.test(value) ? this : empty();
}
//示例:
List<String > list = new ArrayList<>();
list.add("1");
List<String> newList = Optional.ofNullable(list).filter((x) -> x.add("3")).get();
三、总结:
Optional类的方法虽然不多,但是麻雀虽小,五脏俱全。Optional本身是一个容器对象,它提供了对于非null值的操作方法,对于对象操作提供了更多的可能性,尤其配合函数式编程和Lambda表达式更能发挥其强大的作用,也可以说Optional是函数式编程和Lambda表达式的最佳实践之一。
参考:Java SE8 API在线文档地址:Java Platform SE 8