whi*_*win 206 java null nullpointerexception optional java-8
使用Java 8 Optional类时,有两种方法可以将值包装在可选项中.
String foobar = <value or null>;
Optional.of(foobar); // May throw NullPointerException
Optional.ofNullable(foobar); // Safe from NullPointerException
Run Code Online (Sandbox Code Playgroud)
我理解Optional.ofNullable是唯一安全的使用方式Optional,但为什么Optional.of存在呢?为什么不Optional.ofNullable 随时使用并保持安全?
Tag*_*eev 269
您的问题是基于可能抛出NullPointerException的代码比不可能抛出的代码更糟糕的假设.这个假设是错误的.如果您希望foobar由于程序逻辑而永远不会为null,那么使用它会好得多,Optional.of(foobar)因为您将看到一个NullPointerException表明您的程序存在错误.如果您使用Optional.ofNullable(foobar)并且foobar碰巧是null由于该错误,那么您的程序将默默地继续正常工作,这可能是一个更大的灾难.这样一来,错误可能会在很晚之后发生,而且在理解它出错的时候会更难理解.
Tad*_*ato 14
这个问题已经有七年多了,但我对最佳答案感到非常沮丧,所以我不得不写下我的答案。
现有答案(包括最佳答案)之所以无法正确回答该问题,是因为原来的问题一开始就不合适。如果你没有提出正确的问题,你将不会得到正确的答案。
原问题的不正确之处在于它比较了错误的一对。中共有三个静态方法java.util.Optional。
Optional#empty()Optional#of(T value)Optional#ofNullable(T value)这对不是ofand ofNullable,而是ofand empty。这是因为这两个是创建新实例的工厂方法,Optional没有提供公共构造函数。
您可以选择of何时empty创建 的新实例Optional。
Optional<Integer> answer = Optional.of(42); // or Optional.empty() if it's absent
Run Code Online (Sandbox Code Playgroud)
在这种用法中,您确定不会传递nullto of(),因为是您正在初始化实例。如果你想创建一个空实例,你可以直接选择empty()。因此,如果您在这个阶段传递一个null值,这显然是一个错误,您应该收到一个 NPE。of()
这个问题的一位评论者建议,由于 比ofNullable更有用,所以如果被命名为和wereof会更好。这个意见很好采纳。但是,当您考虑到和是官方工厂方法时,使用更短的名称定义更常用的方法是有意义的。此外,它也是一个很好的名称,与其他 Java 集合类工厂方法(如、、 )的命名保持一致。ofNullableofofofNotNullofemptyOptionalList#of()Set#of()Map#of()
那么什么是ofNullable?这实际上是一种实用适配器方法,用于将零消除的Optional世界与充满nulls 的遗留世界联系起来。它用于包装在其他地方定义的变量或从外部服务接收的返回值,使Optional它们成为空安全的。
String foo = someExternalAPI();
Optional<String> bar = Optional.ofNullable(foo);
Run Code Online (Sandbox Code Playgroud)
由于这是一个实用程序方法而不是主要工厂方法,因此通常应该可以接受给它一个稍长的名称,并且实用程序方法具有一个描述性名称来清楚地说明其意图甚至是一个很好的做法。
Optional#of(T value)是Optional#empty().of或empty创建一个新Optional实例。ofNullable将现有变量包装为Optional.此外,如果您知道如果object为null,则代码不起作用,则可以使用以下方法引发异常: Optional.orElseThrow
String nullName = null;
String name = Optional.ofNullable(nullName).orElseThrow(NullPointerException::new);
Run Code Online (Sandbox Code Playgroud)
@ tagir-valeev,如果我错了,请更正。