繁体   English   中英

findFirst抛出java.lang.NullPointerException

[英]findFirst throws java.lang.NullPointerException

我在下面有这个代码。 即使我有一个链接的orElseGet调用, findfirst调用也会抛出NullPointerException

int numberOfRetry = 5;
String req = "abc";
String res =
    Stream.iterate(0, n -> n + 1).map(i -> {
        try {
            return req.substring(numberOfRetry - i);
        } catch (Exception e) {
            // log exception
        }
        return null;
    })
    .limit(1)
    .findFirst()
    .orElseGet(() -> "Exception");

但是,如果我进行过滤器调用,它可以正常工作,如下所示:

int numberOfRetry = 5;
String req = "abc";
String res =
    Stream.iterate(0, n -> n + 1).map(i -> {
        try {
            return req.substring(numberOfRetry - i);
        } catch (Exception e) {
            // log exception
        }
        return null;
    })
    .limit(1)
    .filter(Objects::nonNull)
    .findFirst()
    .orElseGet(() -> "Exception");

我想我们在某些情况下不能显式地返回null ,并且乍一看这些情况并不十分清楚。 在第一种情况下,它返回一个带有null元素的stream ,它抛出NullPointerException ,在第二种情况下,它返回一个工作正常的空流。

您的代码显式返回null

return null

根据Optional.findFirst的规范,此后抛出NPE,其中包括:

 @throws NullPointerException if the element selected is null Optional<T> findFirst(); 

此外,澄清代码控制甚至无法到达orElseGet部分,无论如何假设它在Optional (无论是空的还是有一些值)上工作。


几点建议:

  • 不要忽略异常,特别是当你从中发现了最常见的异常时。
  • 避免在迭代中显式返回null ,这似乎与你为什么要迭代相矛盾。
  • 当前代码中更安全的一面,您可以使用filter仅过滤非null对象

     Stream.iterate(0, n -> n + 1).map(i -> { try { return req.substring(numberOfRetry - i); } catch (Exception e) { err.add(e); } return null; }) .filter(Objects::nonNull) .limit(1) .findFirst() .orElse("Exception"); 

当你这样做时,你认为会发生什么:

System.out.println(req.substring(numberOfRetry - i));

i第一次是zero 将抛出一个越界异常 - 你捕获并返回null ; 所以你有一个你调用了findFirstStream.of(null) - 它被记录为抛出NullPointerException是元素为null的情况。

findFirstjavadoc

抛出:NullPointerException - 如果选择的元素为null

Optional无法区分“存在但无效”和“不存在”

这是因为您在map函数中返回null 尝试在map操作后添加.filter(s -> s != null)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM