在开发中,我们常常需要对一个引用进行判空以防止空指针异常的出现。Java8引入了Optional类,为的就是优雅地处理判空等问题。现在也有很多类库在使用Optional封装返回值,比如Spring Data JPA等。下面,我们就来了解下Optional的常用用法
本文发布于掘金号【Happyjava】。Happy的掘金地址: juejin.im/user/5cc289… ,Happy的个人博客:(blog.happyjava.cn)[blog.happyjava.cn]。欢迎转载,但须保留此段声明。
Optional的方法列表如下:
初始化一个Optional有三种方式,如下:
// 创建一个空的optional Optional<Object> empty = Optional.empty(); // 此方式不可为null Optional<String> optional = Optional.of("Happyjava"); // 此方式可以为null Optional<Object> optional1 = Optional.ofNullable(null); 复制代码
这里需要注意一点,Optional.of初始化一个Optional,是不可以传null值进去的,否则会报空指针异常。
很多人对于Optional只会这么用:
通过isPresent方法判断是否有值,然后通过get方法获取值。虽然这么写没有什么问题,但始终是没用到Optional的精华。
如果存在,则做某事
上面那种写法,我们完全可以用ifPresent来替换:
如果存在,则返回。如果不存在,则提供默认值。我们可以通过orElse方法的入参设置默认值
@Test public void testOrElse() { Optional<Object> optional = Optional.empty(); Object happyjava = optional.orElse("Happyjava"); System.out.println(happyjava); } 复制代码
如果存在,则返回。如果不存在,则由函数来创造值
@Test public void orElseGetTest() { Optional<Object> optional = Optional.empty(); Object name = optional.orElseGet(this::getName); System.out.println(name); } public String getName() { return "Happyjava"; } 复制代码
如果存在,则返回。不存在,则抛出异常。
在业务开发的时候,经常会对一个引用进行判空,如果为空,则采用异常流的形式处理业务逻辑。常见代码如下:
@Test public void testTest() { User user = userRepo.findById(1); if(user ==null){ throw new WebException("用户不存在"); } // 继续业务逻辑 } 复制代码
如果采用Optional的话,可以这么写:
@Test public void testElseThrow() { Optional<Object> optional = Optional.empty(); Object o = optional.orElseThrow(() -> { throw new RuntimeException("xxx不存在"); }); } 复制代码
这段代码,在JDK8中是编译不过的,会提示有受检异常未处理。搜索了下,这似乎是JDK的bug。我演示用的是JDK11。
map方法用来返回一个新的Optional,也可以说用来组装一个新的Optional。
如:
Optional<String> name = Optional.of("Happyjava"); Optional<String> upperName = name.map((value) -> value.toUpperCase()); System.out.println(upperName.orElse("No value found")); 复制代码
flatMap也是返回一个Optional。其与map的区别在于:map是把结果自动封装成一个Optional,但是flatmap需要你自己去封装。
Optional<String> name = Optional.of("Happyjava"); Optional<String> opt = name.flatMap(e -> Optional.of(e.toLowerCase())); System.out.println(opt.orElse("No value found")); 复制代码
如果有值并且满足断言条件返回包含该值的Optional,否则返回空Optional。
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的形式。
搜索公众号【Happyjava】,回复【电子书】和【视频】,即可获取大量优质电子书和大数据、kafka、nginx、MySQL等视频资料