Java 9 Optional 新特性详解

本文详细介绍了Java 9中Optional类的三个重要更新:ifPresentOrElse、or和stream方法。这些新增方法让处理可能为空的值变得更加优雅和高效,帮助开发者编写更清晰、更健壮的代码,有效避免空指针异常。

Java 9: Optional 的更新

在本系列的前一篇文章中,我们探讨了Java 9中Stream API的新特性。与Stream配合良好,并且实际上使Stream更加健壮的一个非常有用的API是Optional。让我们用JShell来探索它!

Optional提供了一个可能包含也可能不包含非空值的容器。它在Java 8中引入,旨在减少代码中可能产生NullPointerException的地方。

其基本API相当简单。我们可以创建一个空的Optional:

1
2
jshell> Optional.empty()
$1 ==> Optional.empty

或者一个包含某些内容的Optional:

1
2
jshell> Optional.of("something")
$2 ==> Optional[something]

我们可以检查是否存在值:

1
2
3
4
5
jshell> Optional.empty().isPresent()
$3 ==> false

jshell> Optional.of("something").isPresent()
$4 ==> true

我们还可以调用Optional暴露的相对简单API中的任何其他方法:

1
2
3
4
5
jshell> Optional.of("something").
equals(            filter(            flatMap(           get()              getClass()
hashCode()         ifPresent(         ifPresentOrElse(   isPresent()        map(
notify()           notifyAll()        or(                orElse(            orElseGet(
orElseThrow(       stream()           toString()         wait(

JDK 9添加了其中三个方法:ifPresentOrElseorstream,这些方法在某种程度上帮助我们处理默认值。

1. ifPresentOrElse

自Java 8以来,Optional提供了一个名为ifPresent的方法。该方法检查给定的Optional中是否存在值,如果找到,则对该值执行操作。否则,该方法不执行任何操作。例如:

1
2
3
4
jshell> Optional.empty().ifPresent(System.out::println)

jshell> Optional.of("something").ifPresent(System.out::println)
something

Java 9引入了ifPresentOrElse。该方法的行为类似于ifPresent,但它允许我们指定在Optional中没有值时要执行的默认操作。例如:

1
2
3
4
5
jshell> Optional.empty().ifPresentOrElse(System.out::println, () -> System.out.println("empty"))
empty

jshell> Optional.of("something").ifPresentOrElse(System.out::println, () -> System.out.println("empty"))
something

当我们想要对值执行特定操作,但又想跟踪何时无法执行该操作时(例如通过触发事件、记录消息或更新指标),这非常有用。

2. or

or方法检查给定的Optional是否包含值。如果存在值,则返回描述该值的Optional(同一个Optional)。如果没有值存在,则返回由供应函数生成的新Optional。

该方法类似于我们从Java 8中了解的另外两个方法:orElseorElseGet

orElse如果给定Optional中存在值,则返回该值。否则,返回调用者提供的默认值。例如:

1
2
3
4
5
jshell> Optional.of("something").orElse("empty")
$5 ==> "something"

jshell> Optional.empty().orElse("empty")
$6 ==> "empty"

orElse类似,orElseGet如果Optional中存在值,则返回该值。然而,与orElse不同的是,orElseGet允许我们指定一个供应函数,在Optional中没有值时返回默认值。例如:

1
2
3
4
5
jshell> Optional.of("something").orElseGet(() -> "empty")
$7 ==> "something"

jshell> Optional.empty().orElseGet(() -> "empty")
$8 ==> "empty"

orElseorElseGet的共同点是它们返回Optional内部的值,而不是Optional本身。这就是新的or方法的用途:

1
2
3
4
5
jshell> Optional.of("something").or(() -> Optional.of("empty"))
$9 ==> Optional[something]

jshell> Optional.empty().or(() -> Optional.of("empty"))
$10 ==> Optional[empty]

尽管可能不是立即显而易见,但这个方法对于提供一种流畅的方式来链式操作Optional非常有用,而无需在容器和它们包装的值之间来回切换。

3. stream

API的另一个有用补充是stream方法。如果给定Optional中存在值,该方法返回一个仅包含该值的流。否则返回一个空流。例如:

1
2
3
4
jshell> Optional.of("something").stream().forEach(System.out::println)
something

jshell> Optional.empty().stream().forEach(System.out::println)

在某种程度上,stream方法类似于流上的ofNullable方法。如果我们想利用流的惰性特性,它非常有用——例如,比较Optional上map方法的急切行为与流上map方法的惰性行为。当操作Optional流时,该方法也很有用。例如,当需要处理Optional流时,它特别适合作为传递给流上flatMap方法的映射器。

总体而言,Java 9中对Optional的添加可能看起来很小,但它们允许我们编写更清晰的代码,这非常令人兴奋。试试它们吧!

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计