在程序运行时,空指针异常应该是最常见的异常之一,因此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<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