findFirst выбрасывает java.lang.NullPointerException - PullRequest
0 голосов
/ 15 октября 2018

У меня есть этот код ниже.Вызов findfirst выбрасывает NullPointerException, хотя у меня orElseGet прикован вызов

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 в некоторых ситуациях, и не совсем понятно, что это за ситуации на первый взгляд.В первом случае он возвращает stream с элементом null, который выбрасывает NullPointerException, во втором случае возвращает пустой поток, который работает нормально.

Ответы [ 4 ]

0 голосов
/ 15 октября 2018

Что, по вашему мнению, происходит, когда вы делаете:

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

, где i в первый раз равен zero?Будет сгенерировано исключение вне пределов - которое вы ловите и возвращаете null;так что у вас есть Stream.of(null), который вы называете findFirst на - который задокументирован, чтобы выбросить, что NullPointerException - это случай, когда элемент равен нулю.

0 голосов
/ 15 октября 2018

Это происходит потому, что вы возвращаете null в своей функции карты.Попробуйте добавить .filter(s -> s != null) после map операции.

0 голосов
/ 15 октября 2018

Ваш код явно возвращает null

return null

, который затем генерирует NPE, в соответствии со спецификацией Optional.findFirst, которая гласит:

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

Кроме того, чтобы уточнить, элемент управления кодом не может даже достичь части orElseGet, которая в любом случае предположительно работает над Optional (либо пустым, либо с некоторым значением).


Несколько предложений:

  • Не игнорируйте исключения, особенно когда вы уловили самые общие из них.
  • Избегайте явного возврата null из итерации,кажется противоречивым, почему вы будете выполнять итерацию тогда.
  • Более безопасная сторона в вашем коде в настоящее время , вы можете фильтровать только объекты не Null, используя filter как

    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");
    
0 голосов
/ 15 октября 2018

Из javadoc для findFirst:

Броски: NullPointerException - если выбранный элемент является нулем

Optional не может дифференцироватьсямежду «присутствует, но ноль» и «нет»

...