简体   繁体   English

findFirst抛出java.lang.NullPointerException

[英]findFirst throws java.lang.NullPointerException

I have this code below. 我在下面有这个代码。 The findfirst call is throwing NullPointerException even though I have an orElseGet call chained 即使我有一个链接的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");

However, it works fine if I put a filter call as shown below: 但是,如果我进行过滤器调用,它可以正常工作,如下所示:

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");

I guess we cannot explicitly return null in some situations, and it is not quite clear what those situations are at first glance. 我想我们在某些情况下不能显式地返回null ,并且乍一看这些情况并不十分清楚。 In the first case it returns a stream with the null element in it which throws NullPointerException , in the second case it returns an empty stream which works fine. 在第一种情况下,它返回一个带有null元素的stream ,它抛出NullPointerException ,在第二种情况下,它返回一个工作正常的空流。

Your code is explicitly returning null 您的代码显式返回null

return null

which thereafter throws NPE, according to the spec of Optional.findFirst which reads: 根据Optional.findFirst的规范,此后抛出NPE,其中包括:

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

Also, to clarify the code control couldn't even reach the orElseGet part which anyway assumingly works over an Optional (either empty or with some value). 此外,澄清代码控制甚至无法到达orElseGet部分,无论如何假设它在Optional (无论是空的还是有一些值)上工作。


Few suggestions : 几点建议:

  • Don't ignore exceptions, especially when you've caught the most generic out of them all. 不要忽略异常,特别是当你从中发现了最常见的异常时。
  • Avoid returning null explicitly from within an iteration, it seems contradictory to why you'd iterate then. 避免在迭代中显式返回null ,这似乎与你为什么要迭代相矛盾。
  • Safer side in your code currently , you can filter-in only nonNull objects using filter as 当前代码中更安全的一面,您可以使用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"); 

What do you think happens when you do: 当你这样做时,你认为会发生什么:

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

where i for the first time is zero ? i第一次是zero An out of bounds exception will be thrown - which you catch and return null ; 将抛出一个越界异常 - 你捕获并返回null ; so you have a Stream.of(null) which you call findFirst on - which is documented to throw that NullPointerException is case the element is null. 所以你有一个你调用了findFirstStream.of(null) - 它被记录为抛出NullPointerException是元素为null的情况。

From the javadoc for findFirst : findFirstjavadoc

Throws: NullPointerException - if the element selected is null 抛出:NullPointerException - 如果选择的元素为null

Optional cannot differentiate between "present but null" and "not present" Optional无法区分“存在但无效”和“不存在”

It happens because you return null in your map function. 这是因为您在map函数中返回null Try to add .filter(s -> s != null) after map operation. 尝试在map操作后添加.filter(s -> s != null)

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

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