本文介绍optional
1 Optional 类包含的方法:
1 of
为非null的值创建一个Optional。of方法通过工厂方法创建Optional类。需要注意的是,创建对象时传入的参数不能为null。如果传入参数为null,则抛出NullPointerException 。
1 | //调用工厂方法创建Optional实例 |
2 ofNullable
为指定的值创建一个Optional,如果指定的值为null,则返回一个空的Optional。ofNullable与of方法相似,唯一的区别是可以接受参数为null的情况。
1 | //下面创建了一个不包含任何值的Optional实例 |
3 isPresent
如果值存在返回true,否则返回false。
1 | //isPresent方法用来检查Optional实例中是否包含值 |
4 get
如果Optional有值则将其返回,否则抛出NoSuchElementException。
1 | //执行下面的代码会输出:No value present |
5 ifPresent
如果Optional实例有值则为其调用consumer,否则不做处理。
1 | //ifPresent方法接受lambda表达式作为参数。 |
6 orElse
如果Optional实例有值则将其返回,否则返回orElse方法传入的参数。
1 | //如果值不为null,orElse方法返回Optional实例的值。 |
7 orElseGet
orElseGet与orElse方法类似,区别在于得到的默认值。orElse方法将传入的字符串作为默认值,orElseGet方法可以接受Supplier接口的实现用来生成默认值。
1 | //orElseGet与orElse方法类似,区别在于orElse传入的是默认值, |
8 orElseThrow
如果有值则将其返回,否则抛出supplier接口创建的异常。
1 | try { |
9 map
如果有值,则对其执行调用mapping函数得到返回值。如果返回值不为null,则创建包含mapping返回值的Optional作为map方法返回值,否则返回空Optional。
1 | //map方法执行传入的lambda表达式参数对Optional实例的值进行修改。 |
10 flatMap
如果有值,为其执行mapping函数返回Optional类型返回值,否则返回空Optional。flatMap与map(Funtion)方法类似,区别在于flatMap中的mapper返回值必须是Optional。调用结束时,flatMap不会对结果用Optional封装。而map方法的mapping函数返回值可以是任何类型T,调用结束时,map一定会对结果用Optional封装,如果mapper返回值是Optional,那么map就会将结果封装成Optional
1 | Optional<String> name = Optional.ofNullable("Walker"); |
11 filter
filter个方法通过传入限定条件对Optional实例的值进行过滤。如果有值并且满足断言条件返回包含该值的Optional,否则返回空Optional。
1 | //filter方法检查给定的Option值是否满足某些条件。 |
2 使用Optional的正确姿势
错误的姿势:
1 | User user; |
这和之前的写法没有任何区别
1 | if (user != null) { |
当我们还在以如下几种方式使用 Optional 时, 就得开始检视自己了
- 调用
isPresent()
方法时 - 调用
get()
方法时 - Optional 类型作为类/实例属性时
- Optional 类型作为方法参数时
isPresent() 与 obj != null 无任何分别, 我们的生活依然在步步惊心. 而没有 isPresent() 作铺垫的 get() 调用在 IntelliJ IDEA 中会收到告警。把 Optional 类型用作属性或是方法参数在 IntelliJ IDEA 中更是强力不推荐的。
所以 Optional 中我们真正可依赖的应该是除了 isPresent()
和 get()
的其他方法。
正确的姿势
创建Optional对象:
1 | Optional<Soundcard> sc = Optional.empty(); |
存在即返回, 无则提供默认值:
1 | return user.orElse(null); //而不是 return user.isPresent() ? user.get() : null; |
存在即返回, 无则由函数来产生:
1 | return user.orElseGet(() -> fetchAUserFromDatabase()); |
存在才对它做点什么:
1 | user.ifPresent(System.out::println); |
使用map抽取特定的值或者做值的转换:
1 | return user.map(u -> u.getOrders()).orElse(Collections.emptyList()) |
级联使用map:
1 | return user.map(u -> u.getUsername()) |
这样避免了连续的空值判断:
1 | User user = ..... |
级联的Optional对象使用flatMap:
1 | String version = computer.flatMap(Computer::getSoundcard) |
使用filter拒绝特定的值:
1 | Optional<USB> maybeUSB = ...; |
用了 isPresent() 处理 NullPointerException 不叫优雅, 有了 orElse, orElseGet 等, 特别是 map 方法才叫优雅.