Java 8 Optional 类
- 总述
- 类声明
- 类常用的方法
- Optional 实例
- Optional在SpringBoot中的应用之一
- 另附一张Optional的API
总述
Optional 为java8的新特性
Optional 类是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。
Optional 是个容器:它可以保存类型T的值,或者仅仅保存null。Optional提供很多有用的方法,这样我们就不用显式进行空值检测。
Optional 类的引入很好的解决空指针异常。
类声明
java.util.optional类的声明
public filnal class Optional extends Object
类常用的方法
序号 | 方法 | 描述 |
---|---|---|
1 | static Optional empty() | 返回空的 Optional 实例。 |
2 | boolean equals(Object obj) | 判断其他对象是否等于 Optional。 |
3 | Optional filter(Predicate<? super predicate>) | 如果值存在,并且这个值匹配给定的 predicate,返回一个Optional用以描述这个值,否则返回一个空的Optional。 |
4 | Optional flatMap(Function< ? Super T>,Optional mapper) | 如果值存在,返回基于Optional包含的映射方法的值,否则返回一个空的Optional |
5 | T get() | 如果在这个Optional中包含这个值,返回值,否则抛出异常:NoSuchElementException |
6 | boolean isPresent() | 如果值存在则方法会返回true,否则返回 false。 |
7 | static Optional of(T value) | 返回一个指定非null值的Optional。 |
8 | static Optional ofNullable(T value) | 如果为非空,返回 Optional 描述的指定值,否则返回空的 Optional。 |
9 | T orElse(T other) | 如果存在该值,返回值, 否则返回 other。 |
10 | T orElseGet(Supplier<? extends T> other) | 如果存在该值,返回值, 否则触发 other,并返回 other 调用的结果。 |
11 | T orElseThrow(Supplier<? extends X> exceptionSupplier) | 如果存在该值,返回包含的值,否则抛出由 Supplier 继承的异常 |
Optional 实例
import java.util.Optional;
public class Java8Tester {
public static void main(String args[]){
Java8Tester java8Tester = new Java8Tester();
Integer value1 = null;
Integer value2 = new Integer(10);
// Optional.ofNullable - 允许传递为 null 参数
Optional<Integer> a = Optional.ofNullable(value1);
// Optional.of - 如果传递的参数是 null,抛出异常 NullPointerException
Optional<Integer> b = Optional.of(value2);
System.out.println(java8Tester.sum(a,b));
}
public Integer sum(Optional<Integer> a, Optional<Integer> b){
// Optional.isPresent - 判断值是否存在
System.out.println("第一个参数值存在: " + a.isPresent());
System.out.println("第二个参数值存在: " + b.isPresent());
// Optional.orElse - 如果值存在,返回它,否则返回默认值
Integer value1 = a.orElse(new Integer(0));
//Optional.get - 获取值,值需要存在
Integer value2 = b.get();
return value1 + value2;
}
}
输出结果为:
$ javac Java8Tester.java
$ java Java8Tester
第一个参数值存在: false
第二个参数值存在: true
10
示例重点解析:正常情况为value1 + value2=null+10会报错,使用Optional后可以计算值
Optional在SpringBoot中的应用之一
Spring Boot 2.0中,在将原来的泛型改为了Optional,旨在让我们的代码更简洁。
Optional findById(ID var1)
实践
Optional
很简单的一个类,点开它的源代码,其中所有的方法都是与null相关联的。

这是一个简化我们处理null的类。
它就是一个容器,其中有我们想要的对象,但是该对象有时候会是空,所以我们需要使用Optional封装好的方法来获取需要的对象。从而很好地避免了空指针异常。
错误示范
我看到网上很多人这么写:catRepository.findById(id).get();
下面是Spring Boot 1.5的写法,那请问:如果上面的写法是正确的,那为什么还要大费周章设计一个Optional呢?
catRepository.findOne(id);
分析
通过get是能获取到我们需要的对象。
但是看看get的源代码,这样写,抛出了NoSuchElementException异常,这个异常我们没法在全局中处理它。
public T get() {
if (value == null) {
throw new NoSuchElementException("No value present");
}
return value; }
因为NoSuchElementException覆盖的范围太广了,只要是Optional中有null就会抛出NoSuchElementException,很多情况下都会造成这种异常,那我们究竟要给用户一个什么样的提示信息好呢?最后还是给出500服务器异常,那异常处理的意义何在呢?
所以我们需要用Optional来抛出一个有特定范围的能被全局准确处理的异常。
Cat cat = catRepository.findOne(id);
if (null == cat) {
throw new EntityNotFoundException("该实体找不到");
}
return cat;
思想都是一样,我们不过是用一种更简洁的写法实现上面的功能。
实现
没错,就像下面一样,我们只需要一行代码!
public Cat findById(Long id) {
return catRepository.findById(id).orElseThrow(EntityNotFoundException::new); }
findById返回一个Optional,然后调用该对象的orElseThrow方法。
orElseThrow方法,如果存在,返回包含的值,否则抛出异常。
该方法的参数是一个lamda表达式。这里就不深究lamda表达式的几种类型了,如果感兴趣可以自行研究下Function、Consumer、Predicate、Supplier这四个函数式接口的区别。
所以传一个lamda表达式进去,然后IDEA会给出警告:
Can be replaced with method reference
该lamda表达式能被一个方法引用代替,Alt + Enter,我们最终的代码就长这样:
这里的::是lamda表达式的一种简写,是Java8中的新特性,看着可能有点奇怪,原来,编译器比程序员聪明多了。
异常处理
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(EntityNotFoundException.class)
public ResponseEntity<String> entityNotFoundHandler() {
return new ResponseEntity<>("您要找的实体不存在", HttpStatus.NOT_FOUND); } }
写个控制器增强,全局处理异常,这里的RestControllerAdvice又是一个组合注解:
处理异常,同时以Json的格式返回。