听到同事们说Optional类是Java1.8新增的类可以用来判断对象是否为null。当时感到一丝丝疑问:为了判null至于新出一个类吗?直到了学习了官方文档和实际演示了一遍,发现Optional并不是只是判null这么简单。
Java1.8发布了十来年,实际也使用了四五年,今天才开始正式学习新增的特新之一。实在汗颜。废话不多说了,来看看Optional类是如何处理对象为空的情况。
一、简单应用来看下常规是的示例:
Listlist = null; if(null != list){ list.forEach((String a )->System.out.println(a)); }
通常情况下,当接收的对象可能存在null时,我们可能会增加一层判空条件来避免万恶的空指针。
而Optional给我们又提供了一种的新的处理方式:通过增加一个默认的返回对象,来避免空指针。
Listlist = null; Optional.ofNullable(list).orElse(Arrays.asList("1","2","3")).forEach((String a )->System.out.println(a));
通过调用Optional类的ofNullable和orElse方法就规避了空指针的情况。
那Optional类是如何解决的这种情况,看下Optional的源码:
public static Optional ofNullable(T value) {
return value == null ? empty() : of(value);
}
public static Optional empty() {
@SuppressWarnings("unchecked")
Optional t = (Optional) EMPTY;
return t;
}
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{ //构造方法 private Optional() { this.value = null; } private Optional(T value) { this.value = Objects.requireNonNull(value); } //静态方法 public static Optional of(T value) { return new Optional<>(value); } public static Optional ofNullable(T value) { return value == null ? empty() : of(value); } public static Optional empty() { @SuppressWarnings("unchecked") Optional t = (Optional ) 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> optionalStringList = Optional.ofNullable(new ArrayList<>());
if(optionalStringList.isPresent()){
List list = optionalStringList.get();
}
}
//示例2
Optional> 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> mapper);
这两个实例方法依然可以通过函数对指定类型处理,两个方法区别是 map(Function super T, ? extends U> mapper)方法可以返回其他指定的类型的Optional,也就是你给了我什么,我不一定还给你什么。而flatMap(Function super T, Optional> mapper)应为做了限定,所以也就是你给什么我就还给你什么。
//源码
public Optional map(Function super T, ? extends U> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else {
return Optional.ofNullable(mapper.apply(value));
}
}
public Optional flatMap(Function super T, Optional> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else {
return Objects.requireNonNull(mapper.apply(value));
}
}
//示例
List list = new ArrayList();
list.add("1");
Optional> optionalStringList = Optional.ofNullable(list);
Optional> optionalStringList1 = optionalStringList.flatMap(list2 -> {
list2.add("4");
return optionalStringList;
});
List strings1 = optionalStringList.get();
//示例
Optional> optionalStringList2 = Optional.ofNullable(Arrays.asList("1", "2", "3"));
Optional> stringStringHashMap = optionalStringList2.map(list3 -> {
HashMap map = new HashMap<>();
for (int i = 0; i < list3.size(); i++) {
map.put(list3.get(i), String.valueOf(i));
}
return map;
});
HashMap 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 strings = Optional.ofNullable(Arrays.asList("1")).orElse(new ArrayList<>());
//源码
public T orElseGet(Supplier extends T> other) {
return value != null ? value : other.get();
}
//示例
Optional> optionalStringList2 = Optional.ofNullable(Arrays.asList("4","5","6"));
Optional> optionalStringList = Optional.ofNullable(Arrays.asList("1","2","3")).orElseGet(() -> {
return optionalStringList2.get()
});
//源码 publicT 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三、总结:filter(Predicate super T> predicate) { Objects.requireNonNull(predicate); if (!isPresent()) return this; else return predicate.test(value) ? this : empty(); } //示例: List list = new ArrayList<>(); list.add("1"); List newList = Optional.ofNullable(list).filter((x) -> x.add("3")).get();
Optional类的方法虽然不多,但是麻雀虽小,五脏俱全。Optional本身是一个容器对象,它提供了对于非null值的操作方法,对于对象操作提供了更多的可能性,尤其配合函数式编程和Lambda表达式更能发挥其强大的作用,也可以说Optional是函数式编程和Lambda表达式的最佳实践之一。
参考:Java SE8 API在线文档地址:Java Platform SE 8



