天天看点

java8新特性 Optional总述类声明类常用的方法Optional 实例Optional在SpringBoot中的应用之一另附一张Optional的API

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相关联的。

java8新特性 Optional总述类声明类常用的方法Optional 实例Optional在SpringBoot中的应用之一另附一张Optional的API

这是一个简化我们处理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会给出警告:

java8新特性 Optional总述类声明类常用的方法Optional 实例Optional在SpringBoot中的应用之一另附一张Optional的API

Can be replaced with method reference

该lamda表达式能被一个方法引用代替,Alt + Enter,我们最终的代码就长这样:

java8新特性 Optional总述类声明类常用的方法Optional 实例Optional在SpringBoot中的应用之一另附一张Optional的API

这里的::是lamda表达式的一种简写,是Java8中的新特性,看着可能有点奇怪,原来,编译器比程序员聪明多了。

异常处理

@RestControllerAdvice
public class GlobalExceptionHandler {    
 @ExceptionHandler(EntityNotFoundException.class)   
 public ResponseEntity<String> entityNotFoundHandler() {    
  return new ResponseEntity<>("您要找的实体不存在", HttpStatus.NOT_FOUND);   } } 
           

写个控制器增强,全局处理异常,这里的RestControllerAdvice又是一个组合注解:

处理异常,同时以Json的格式返回。

另附一张Optional的API

java8新特性 Optional总述类声明类常用的方法Optional 实例Optional在SpringBoot中的应用之一另附一张Optional的API