前言
在开发中,我们常常需要对一个引用进行判空以防止空指针异常的出现。Java8引入了Optional类,为的就是优雅地处理判空等问题。现在也有很多类库在使用Optional封装返回值,比如Spring Data JPA等。下面,我们就来了解下Optional的常用用法
Optional方法列表
Optional的方法列表如下:

初始化
初始化一个Optional有三种方式,如下:
1 2 3 4 5 6
| Optional<Object> empty = Optional.empty();
Optional<String> optional = Optional.of("Happyjava");
Optional<Object> optional1 = Optional.ofNullable(null);
|
这里需要注意一点,Optional.of初始化一个Optional,是不可以传null值进去的,否则会报空指针异常。
Optional初级用法
很多人对于Optional只会这么用:

通过isPresent方法判断是否有值,然后通过get方法获取值。虽然这么写没有什么问题,但始终是没用到Optional的精华。
ifPresent
如果存在,则做某事
上面那种写法,我们完全可以用ifPresent来替换:

orElse
如果存在,则返回。如果不存在,则提供默认值。我们可以通过orElse方法的入参设置默认值
1 2 3 4 5 6
| @Test public void testOrElse() { Optional<Object> optional = Optional.empty(); Object happyjava = optional.orElse("Happyjava"); System.out.println(happyjava); }
|
orElseGet
如果存在,则返回。如果不存在,则由函数来创造值
1 2 3 4 5 6 7 8 9 10
| @Test public void orElseGetTest() { Optional<Object> optional = Optional.empty(); Object name = optional.orElseGet(this::getName); System.out.println(name); }
public String getName() { return "Happyjava"; }
|
orElseThrow(常用)
如果存在,则返回。不存在,则抛出异常。
在业务开发的时候,经常会对一个引用进行判空,如果为空,则采用异常流的形式处理业务逻辑。常见代码如下:
1 2 3 4 5 6 7 8
| @Test public void testTest() { User user = userRepo.findById(1); if(user ==null){ throw new WebException("用户不存在"); } }
|
如果采用Optional的话,可以这么写:
1 2 3 4 5 6 7
| @Test public void testElseThrow() { Optional<Object> optional = Optional.empty(); Object o = optional.orElseThrow(() -> { throw new RuntimeException("xxx不存在"); }); }
|
这段代码,在JDK8中是编译不过的,会提示有受检异常未处理。搜索了下,这似乎是JDK的bug。我演示用的是JDK11。
map
map方法用来返回一个新的Optional,也可以说用来组装一个新的Optional。
如:
1 2 3
| Optional<String> name = Optional.of("Happyjava"); Optional<String> upperName = name.map((value) -> value.toUpperCase()); System.out.println(upperName.orElse("No value found"));
|
flatMap
flatMap也是返回一个Optional。其与map的区别在于:map是把结果自动封装成一个Optional,但是flatmap需要你自己去封装。
1 2 3
| Optional<String> name = Optional.of("Happyjava"); Optional<String> opt = name.flatMap(e -> Optional.of(e.toLowerCase())); System.out.println(opt.orElse("No value found"));
|
filter
如果有值并且满足断言条件返回包含该值的Optional,否则返回空Optional。
1 2 3 4 5
| Optional<String> optional = Optional.of("Happyjava"); Optional<String> opt = optional.filter(s -> { return s.length() > 9; }); System.out.println(opt.orElse("empty"));
|
此代码会输出empty
总结
Optional是Java8引入的特性,不见得我们会把自己的方法返回值封装成Optional,但是学习Optional还是很有必要的,比如Spring Data JPA框架现在把返回结果封装成Optional的形式。