对于Java开发者肯定遇到过 NullPointerException 这个异常。在Java中Null是非常常见的,例如默认类的字段被初始化为null。
返回null会发生什么问题
一般来讲API的设计者会在Javadoc中详细介绍会返回null的方法,但是使用者很有可能没有详细阅读Javadoc从而忽略了这个问题,这就会导致使用者使用API的时候忘记进行null检测。从而导致抛出 NullPointerException。
在Java 8 中如何解决这个问题
Java 8引入了Optional来解决null的问题,一个Optional要么包含一个非空的引用对象,要么什么都不包含。注意,这里说的什么都不包含,并不是说Optional包含了null。
Optional<Integer> canBeEmpty1 = Optional.of(5);
canBeEmpty1.isPresent(); // returns true
canBeEmpty1.get(); // returns 5
Optional<Integer> canBeEmpty2 = Optional.empty();
canBeEmpty2.isPresent(); // returns false
可以将Optional看作单值容器,要么包含一个值,要么不包含。注意,Optional并不能完全替代所有的null引用,它的主要作用是用来设计更易理解的API,当一个函数返回的是Optional的时候,调用者就会注意需要检测其是否有值才能够调用。
使用Optional
创建Optional对象
主要有三种创建Optional对象的方法 1. 使用 Optional.empty() 创建一个空的Optional
Optional<Integer> possible = Optional.empty();
- 使用Optional.of() 创建一个非null的值。
Optional<Integer> possible = Optional.of(5);
- 使用Optional.ofNullable() 创建一个可以包含空值的Optional对象,如果参数是null,则返回一个空的Optional
Optional<Integer> possible = Optional.ofNullable(null);
//or
Optional<Integer> possible = Optional.ofNullable(5);
处理Optional的值
当得到一个Optional的值的时候,首先需要检查其是否包含了值
Optional<Integer> possible = Optional.of(5);
possible.ifPresent(System.out::println);
当然上面的代码也可以通过下面的方式重写:
if(possible.isPresent()){
System.out.println(possible.get());
}
不过这么做并不推荐,因为这个处理null没啥区别。推荐使用上面的代码
返回Optional
一般来讲对于方法如果最终需要返回null的时候,都会返回一个默认值以便替换null,使用Optional可以使用如下的方式返回
Optional<Company> companyOptional = Optional.empty();
// 检查Optional,如果有值直接返回,否则返回 new Company();
Company company = companyOptional.orElse(new Company());
// 检查Optional,如果有值直接返回,否则返回 抛出异常;
Company company = companyOptional.orElseThrow(IllegalStateException::new);
在Filter中使用Optional
例如:
Optional<Company> companyOptional = Optional.empty();
companyOptional.filter(department -> "Finance".equals(department.getName())
.ifPresent(() -> System.out.println("Finance is present"));)
filter 函数接受一个Predicate接口作为参数,如果Optional中存在值,那么就会匹配直接输出。
深入理解Optional
在Optional.java 中,Optional的定义如下:
/**
* If non-null, the value; if null, indicates no value is present
*/
private final T value;
如果定义的是一个空的Optional,则直接返回EMPTY的常量
/**
* Common instance for {@code empty()}.
*/
private static final Optional<?> EMPTY = new Optional<>();
当创建一个Optional的时候调用:
this.value = Objects.requireNonNull(value);
从Optional获取值的时候:
public T get() {
if (value == null) {
throw new NoSuchElementException("No value present");
}
return value;
}
结论
Optional 的目的并不是要完全替代null引用,而且为了设计更友好的API而设计的。