参考:
- https://www.jianshu.com/p/d81a5f7c9c4e
- https://zhuanlan.zhihu.com/p/40966718
- https://blog.kaaass.net/archives/764
简介
Optional 是 Java8 提供的为了解决 null 安全问题的一个 API。善用 Optional 可以使我们代码中很多繁琐的设计变得十分优雅。
示例
为了方便,我们先定义一个简单的实体类 Book。
public class Book {
private String name;
private float price;
public Book(String name, float price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", price=" + price +
'}';
}
}
然后看个例子,传统写法如下:
public static String getName(Book book) {
if (book == null || book.getName() == null)
return "Unknown";
return book.getName();
}
使用 Optional 改为链式调用如下:
public static String getName(Book book) {
return Optional.ofNullable(book)
.map(user->user.getName())
.orElse("Unknown");
}
不推荐的写法如下,这其实只是用 isPresent
方法来替代 u==null
。
public static String getName(Book book) {
Optional<Book> myBook = Optional.ofNullable(book);
if (!myBook.isPresent())
return "Unknown";
return myBook.get().getName();
}
构造方法
Java 提供三个静态方法来构造一个Optional:
- Optional.of(T value),该方法通过一个非 null 的 value 来构造一个 Optional,返回的 Optional 包含了 value 这个值。对于该方法,传入的参数一定不能为 null,否则便会抛出 NullPointerException。
Optional<String> optStr1 = Optional.of("optional");
- Optional.ofNullable(T value),该方法和 of 方法的区别在于,传入的参数可以为 null , 但是前面 javadoc 不是说 Optional 只能包含非 null 值吗?原来该方法会判断传入的参数是否为 null,如果为 null 的话,返回的就是 Optional.empty()。
Optional<String> optStr2 = Optional.ofNullable(null);
- Optional.empty(),该方法用来构造一个空的 Optional,即该 Optional 中不包含值,其实底层实现还是 如果 Optional 中的 value 为 null 则该 Optional 为不包含值的状态,然后在 API 层面将 Optional 表现的不能包含 null 值,使得 Optional 只存在 包含值 和 不包含值 两种状态。
Optional<String> optStr = Optional.empty();
API方法
介绍一些经常使用的方法。
get
get()方法主要用于返回包装对象的实际值,但是如果包装对象值为null,会抛出NoSuchElementException异常。
示例:
String name = Optional.ofNullable(book).get().getName(); // book 不能为空
方法源码:
public T get() {
if (value == null) {
throw new NoSuchElementException("No value present");
}
return value;
}
isPresent
isPresent()方法用于判断包装对象的值是否非空。
使用示例:
System.out.println(Optional.ofNullable(book).isPresent());
方法源码:
public boolean isPresent() {
return value != null;
}
ifPresent
ifPresent()方法接受一个Consumer对象(消费函数),如果包装对象的值非空,运行Consumer对象的accept()方法。
示例:
public static void printName(Book book) {
Optional.ofNullable(book).ifPresent(b -> System.out.println("The Book name is : " + b.getName()));
}
方法源码:
public void ifPresent(Consumer<? super T> consumer) {
if (value != null)
consumer.accept(value);
}
filter
filter() 方法接受参数为 Predicate 对象,用于对 Optional 对象进行过滤,如果符合 Predicate 的条件,返回 Optional 对象本身,否则返回一个空的 Optional 对象。举例如下:
示例:
public static void filterPrice(Book book) {
Optional.ofNullable(book).filter( b -> b.getPrice() > 10.0).ifPresent(b -> System.out.println("The book price is more than 10.0."));
}
方法源码:
public Optional<T> filter(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate);
if (!isPresent())
return this;
else
return predicate.test(value) ? this : empty();
}
map
map() 方法的参数为 Function(函数式接口)对象,map()方法将 Optional 中的包装对象用 Function 函数进行运算,并包装成新的 Optional 对象(包装对象的类型可能改变)。
public static Optional<Float> getPrice(Book book) {
return Optional.ofNullable(book).map(u -> u.getPrice());
}
方法源码:
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));
}
}
flatMap
跟map()方法不同的是,入参Function函数的返回值类型为 Optional<U>
类型,而不是 U 类型,这样 flatMap() 能将一个二维的Optional对象映射成一个一维的对象。将上例进行faltMap()改写如下:
public static Optional<Float> getPrice(Book book) {
return Optional.ofNullable(book).flatMap(b -> Optional.ofNullable(b.getPrice()));
}
方法源码:
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));
}
}
orElse
orElse()方法功能比较简单,即如果包装对象值非空,返回包装对象值,否则返回入参other的值(默认值)。
示例:
public static String getName(Book book) {
return Optional.ofNullable(book)
.map(user->user.getName())
.orElse("Unknown");
}
方法源码:
public T orElse(T other) {
return value != null ? value : other;
}
orElseGet
orElseGet()方法与orElse()方法类似,区别在于orElseGet()方法的入参为一个Supplier对象,用Supplier对象的get()方法的返回值作为默认值。
示例:
public static String getName(Book book) {
return Optional.ofNullable(book)
.map(user->user.getName())
.orElseGet(() -> "Unkown");
}
方法源码:
public T orElseGet(Supplier<? extends T> other) {
return value != null ? value : other.get();
}
orElseThrow
orElseThrow()方法其实与orElseGet()方法非常相似了,入参都是Supplier对象,只不过orElseThrow()的Supplier对象必须返回一个Throwable异常,并在orElseThrow()中将异常抛出。
示例:
public static String getName(Book book) {
return Optional.ofNullable(book)
.map(user->user.getName())
.orElseThrow(() -> new RuntimeException("Unkown"));
}
方法源码:
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
if (value != null) {
return value;
} else {
throw exceptionSupplier.get();
}
}
网友评论