jer*_*zek 5 java nullpointerexception optional java-8 java-stream
鉴于此代码:
class Foo {
Integer attr;
public Integer getAttr() {return attr;}
}
List<Foo> list = new ArrayList<>();
list.add(new Foo());
list.stream().map(Foo::getAttr).findAny().orElse(null); //A
list.stream().findAny().map(Foo::getAttr).orElse(null); //B
Run Code Online (Sandbox Code Playgroud)
A线投掷
java.lang.NullPointerException:null
而B行返回null.
这种行为的原因是什么?无论findAny()和map()回报Optional<T>.
小智 6
list.stream().map(Foo::getAttr).findAny().orElse(null);
Run Code Online (Sandbox Code Playgroud)
用于流的Java文档说Stream:"返回一个流,该流包含将给定函数应用于此流的元素的结果",而findAny()"可以返回aNullPointerException - 如果选择的元素为null".在类Foo中,默认情况下,Integer(非int)设置为null,因为已声明但未初始化.请参阅基元在Java中查看默认值和对象初始化
初始化不同于:A)类成员(对象和基元)B)局部变量
首先,您的两个代码片段map是不同的操作:
// v--- stream intermediate operation
list.stream().map(Foo::getAttr).findAny().orElse(null); //A
// v---- a Optional utility method
list.stream().findAny().map(Foo::getAttr).orElse(null); //B
Run Code Online (Sandbox Code Playgroud)
并且NullPointerException发生在Stream#findAny操作中,因为它无法接受null值。因为它使用Optional.of而不是Optional.ofNullable。Stream#findAny的文档已经断言:
抛出:
NullPointerException- 如果选择的元素为空
因此,如果您希望A代码片段正常工作,则必须null在调用Stream#findAny之前过滤所有值,例如:
//when no elements in stream, `findAny` will be return a empty by Optional.empty()
// v
list.stream().map(Foo::getAttr).filter(Objects::nonNull).findAny().orElse(null);//A
Run Code Online (Sandbox Code Playgroud)