可选与null.Java 8中Optional的目的是什么?

Jad*_*mas 44 java java-8

在Java 8中,您可以返回Optional而不是a null.Java 8文档说可选是"容器对象,可能包含也可能不包含非空值.如果存在值,isPresent()将返回true,get()将返回值."

在实践中,为什么这有用?此外,是否有任何null优先使用的情况?性能怎么样?

Ale*_* C. 35

在实践中,为什么这有用?

例如,假设您有这个整数流,并且您正在进行过滤:

int x = IntStream.of(1, -3, 5)
                 .filter(x -> x % 2 == 0)
                 .findFirst(); //hypothetical assuming that there's no Optional in the API
Run Code Online (Sandbox Code Playgroud)

您事先不知道过滤器操作将删除Stream中的所有值.

假设API中没有Optional.在这种情况下,应该findFirst返回什么?

唯一可能的方法是抛出一个异常,例如NoSuchElementException,IMO相当烦人,因为我认为它不应该停止执行你的程序(或者你必须捕获异常,也不是很方便)和过滤标准可能比这更复杂.

通过使用Optional,由调用者来检查是否Optional为空(即,如果您的计算结果是否为值).

使用引用类型,您也可以返回null(但null在仅过滤null值的情况下可能是一个可能的值;因此我们回到异常情况).

关于非流使用,除了防止NPE之外,我认为设计更明确的API也有助于说明值可能存在与否.例如,考虑这个类:

class Car {
   RadioCar radioCar; //may be null or not 
   public Optional<RadioCar> getRadioCar() {
        return Optional.ofNullable(radioCar);
   }
}
Run Code Online (Sandbox Code Playgroud)

在这里,你清楚地告诉呼叫者,车内的收音机是可选的,它可能是或不存在.

  • @AlkisMavridis我也很困惑为什么这个答案被如此重视.这里没有任何答案提供令人信服的理由使用`Optional <T>`而不是`null`,而不是Java Stream API与它一起使用.顺便说一句,`Optional <T>`可以向开发人员提供合同提示,但也可以提供适当的文档......在一天结束时,您仍然在检查值是否为空之前对其进行操作.您刚刚将语义从`if(value == null)`更改为`if(optionalValue.isPresent())`.而且你已经承受了一些方法调用的开销. (11认同)
  • 我仍然不明白为什么Optional在这里是必要的.对于Object类型,我们有null.对于基元,我们有它们的对象兄弟,如Integer和Boolean,它们也可以为null以表示"无值".那么期权的好处是什么? (10认同)
  • 实际上,在对 Java 和 Optional 进行了一些研究之后,我的上述说法是 _not_ true。Java 中的类型系统缺乏表现力,也不够强大,无法保证像 SML、F# 和 Haskell 之类的语言一样。即使在使用 Optionals 时,如果不存在值,仍然可能错误地尝试获取值。那。糟透了。 (5认同)
  • 之所以使用Optionals如此有用,是因为Optionals迫使您以无法从`null`调用方法的方式来表示数据。没有Optionals,它不仅可能,而且非常容易。换句话说,您可以避免草率的逻辑和愚蠢的错误。它与便利或冗长无关。 (4认同)
  • 可选不能包含null ... (3认同)

Old*_*eon 18

当Java最初设计时,通常的做法是使用一个特殊的值,通常被称为null表示特殊情况,比如我找不到你想要的东西.这种做法被Java采用.

从那时起,有人建议将这种做法视为反模式,尤其是对象,因为这意味着您必须使用空检查来丢弃代码以实现可靠性和稳定性.例如,当你想要null收集一个集合时,这也是一种痛苦.

现代的态度是使用一种可能存在或不存在价值的特殊物体.这样你就可以安全地创建一个,而不是用任何东西填充它.在这里,您将看到Java 8通过提供Optional对象来鼓励这种最佳实践.

  • 你能详细说明为什么空检查混乱,但是对Optional.isPresent的调用不是吗? (60认同)
  • 如果你只使用Optional作为直接空值检查与`Optional.isPresent`的直接替换它将具有有限的效用(仍然在调用站点给你明确声明值可能不存在,这是好的); 真正的力量来自能够*延迟*错误处理(没有值)到以后的时间和链接map/flatMap/filter等方法而没有if/else块. (17认同)
  • 我也想知道...... (5认同)
  • @shinzou如果一个方法返回一个可选项,你可以立即调用它上面的map/filter/flatMap和friends,而不用担心它是空的; 但所有这些只有在有值时才会运行.当你想处理空案例时,你只需要调用getOrElse和朋友这样做. (5认同)
  • @ user100464 java语言中的错误是它允许null.想象一下,到处都是`@NonNull`的代码库.然后可选,其中null可以发生.这提供了更安全的程序,它是Java之前的方向(例如C++ refs).可选通过将map和flatMap与lambdas一起使用来消除对条件的需要.像这样构造代码可以确保不会忽略空检查.只是禁止调用isPresent,你必须映射以获取数据,你不会出错. (3认同)
  • @DK_ 所以,实际上,原因是 Oracle 对 `filter` 和 `map` 进行了编程,将 `Optional&lt;T&gt;` 考虑在内,而不是执行 `if (entry == null) {}`。对我来说似乎很愚蠢,但我想对每个人来说都是如此。我仍然没有看到这些结构存在的令人信服的理由。 (2认同)
  • @crush `Optional&lt;T&gt;` 还明确表明对象何时可以为 null。例如,在大多数 Java 代码中有很多实例,根据设计,“String”不能为空。然而,因为默认的“String”值是null,所以我们必须跟踪“String”可以/不能为空的位置,或者在使用“String”之前执行空检查。`Optional&lt;T&gt;` 通过显式地将值标记为“可为空”来消除这种歧义。如果我们用“Optional&lt;T&gt;”替换 null 的概念,那么在任何出现非可选“String”的地方,我们都知道它一定有一个值。 (2认同)

Kay*_*man 5

因为您总是知道Optional返回了一个对象,所以它避免了创建繁琐的null检查。流API也大量使用了它。

  • 我认为您的最后一句话确实是使用它的唯一理由。它无法避免必须创建“繁琐的” null检查。访问该值之前,您仍然必须检查该值是否存在。它真正要做的就是使用新的酷炫Java流API。它也可以作为对开发人员的合同提示。除此之外,据我所知,它没有太多价值。 (3认同)