JDK8--08:Optional
阅读原文时间:2023年07月09日阅读:1

在程序运行时,空指针异常应该是最常见的异常之一,因此JDK8提供了Optional来避免空指针异常。

首先说明JDK8新增的Optional及相关方法的使用

Optional的常用操作:
  Optional.of(T value) 创建一个Optional实例
  Optional.empty() 创建一个Optional空实例
  Optional.ofNullable(T value) 不为null,创建一个Optional实例,否则创建一个Optional空实例
  isPresent 判断是否包含值
  orElse(T t) 如果调用的对象包含值,则返回值,否则返回t
  orElseGet(Supplier s) 如果调用对象包含值,则返回值,否则返回s获取的值
  map(Function f) 如果有值对其处理,并返回处理后的Optional,否则返回Optional.empty()
  flatMap(Function f) 与mapleis,要求返回值必须是Optional

接下来逐个演示使用方式

1、Optional.of(T value) 创建一个Optional实例,但是只能创建非空数据

    Optional<Student> optional = Optional.of(new Student("lcl",16));  
    log.info("optional.get()======================{}",optional.get());  
    //可以快速定位NullPointExecption位置  
    Optional<Student> optional1 = Optional.of(null);//320行  
    log.info("optional1.get()======================{}",optional1.get());

运行结果

可以看到,在第一次创建时,new了一个对象作为入参,成功创建了Optional对象,但是第二次创建时,由于入参是空值,因此创建失败,报空指针异常,且报错行数为320行(代码标红处)。

2、Optional.empty() 创建一个Optional空实例

    //Optional.empty()     创建一个Optional空实例  
    Optional<Student> optional2 = Optional.empty(); //324行  
    log.info("optional2.get()======================{}",optional2.get());//325行

运行结果:

可以看到在在324行创建了一个空的Optional,但是由于是空的,因此在325行使用get方法时,报了没有对象的异常信息

3、Optional.ofNullable(T value) 不为null,创建一个Optional实例,否则创建一个Optional空实例

    //Optional.ofNullable(T value)  不为null,创建一个Optional实例,否则创建一个Optional空实例  
    Optional<Student> optional2 = Optional.ofNullable(new Student("lcl",16));//328行  
    log.info("optional2.get()======================{}",optional2.get());  
    Optional<Student> optional3 = Optional.ofNullable(null);  
    log.info("optional3.get()======================{}",optional3.get());

测试结果:

测试结果中,创建optional2时,由于入参是新创建的对象,因此optional2不为空,使用get方法时,正常获取到数据,但是optional3创建时的入参是空,因此创建了一个空的Optional对象,因此使用get方法时,出现异常。

4、isPresent 判断是否包含值(为了防止前几步的异常信息,jdk8提供了判断optional是否为空的方法isPresent)

    Optional<Student> optional = Optional.of(new Student("lcl",16));  
    Optional<Student> optional2 = Optional.ofNullable(new Student("lcl",16));  
    log.info("optional.isPresent()======================{}",optional.isPresent());  
    log.info("optional1.isPresent()======================{}",optional2.isPresent());

测试结果:

2020-06-01 14:58:40.381 INFO 18628 --- [ main] com.example.jdk8demo.Jdk8StreamDemoTest : optional.isPresent()======================true
2020-06-01 14:58:40.383 INFO 18628 --- [ main] com.example.jdk8demo.Jdk8StreamDemoTest : optional1.isPresent()======================true

5、orElse(T t) 如果调用的对象包含值,则返回值,否则返回t

    //ofElse(T t)   如果调用的对象包含值,则返回值,否则返回t  
    Optional<Student> optional = Optional.ofNullable(new Student("mm",25));  
    Optional<Student> optional2 = Optional.ofNullable(null);

    Student student = optional.orElse(new Student("lcl",18));  
    log.info("orElse======================{}",student);  
    student = optional2.orElse(new Student("lcl",18));  
    log.info("orElse======================{}",student);

测试结果:

2020-06-01 15:00:42.765 INFO 18864 --- [ main] com.example.jdk8demo.Jdk8StreamDemoTest : orElse======================{"age":25,"name":"mm"}
2020-06-01 15:00:42.920 INFO 18864 --- [ main] com.example.jdk8demo.Jdk8StreamDemoTest : orElse======================{"age":18,"name":"lcl"}

6、orElseGet(Supplier s) 如果调用对象包含值,则返回值,否则返回s获取的值

    //ofElseGet(Supplier s) 如果调用对象包含值,则返回值,否则返回s获取的值  
    Optional<Student> optional2 = Optional.empty();  
    Student student1 = optional2.orElseGet(()->new Student("mm",16));  
    log.info("orElseGet======================{}",student1);  
    optional2 = Optional.of(new Student("kk",10));  
    Student student2 = optional2.orElseGet(()->new Student("mm",16));  
    log.info("orElseGet======================{}",student2);

测试结果:

2020-06-01 15:00:42.921 INFO 18864 --- [ main] com.example.jdk8demo.Jdk8StreamDemoTest : orElseGet======================{"age":16,"name":"mm"}
2020-06-01 15:00:42.922 INFO 18864 --- [ main] com.example.jdk8demo.Jdk8StreamDemoTest : orElseGet======================{"age":10,"name":"kk"}

备注:这里有个点需要说明一下,就是如果T是一个调用,例如orElse(aaa.getStudent()),那么最好不要使用orElse,要使用orElseGet,因为orElse无论调用对象是否有值,

aaa.getStudent()都会被执行,如果是调用第三方接口,那就每次都会多一次请求,而orEleseGet就没有问题,如果调用对象为不为空,则不会走内置接口。

7、map(Function f) 如果有值对其处理,并返回处理后的Optional,否则返回Optional.empty()

    Optional<Student> optional2 = Optional.of(new Student("kk",10));  
    Optional<String> name = optional2.map((x)->x.getName());  
    log.info("map======================{}",name);

测试结果:

2020-06-01 15:00:42.923 INFO 18864 --- [ main] com.example.jdk8demo.Jdk8StreamDemoTest : map======================Optional[kk]

8、flatMap(Function f) 与mapleis,要求返回值必须是Optional,与map的差异:map返回值为Optional,flatMap返回值为Optional

    optional2 = Optional.of(new Student("kk",10));  
    Optional<String> name1 = optional2.flatMap((x)->Optional.of(x.getName()));  
    log.info("flatMap======================{}",name1);

 测试结果:

2020-06-01 15:05:41.552 INFO 14604 --- [ main] com.example.jdk8demo.Jdk8StreamDemoTest : flatMap======================kk