Почему Streams.allMatch (в Java8) пытается вычислить все выражения, даже если значение можно определить на полпути? - PullRequest
2 голосов
/ 11 марта 2020

Рассмотрим этот фрагмент -

 String a = "hello" , b = null, c = "guru";
  boolean value = Stream
  .of(a, b, b.substring(2),c)
  .allMatch(x -> x != null);

  System.out.println(value);

Это приводит к NPE. Кажется, он делает b.substring(2), а поскольку b равно null, NPE выбрасывается. Почему это состояние оценивается? Второе выражение b равно null и, следовательно, имеет значение false. Таким образом, allMatch будет ложным независимо от значений истинности последующих операций. В таком случае, почему он пытается оценить b.substring(2)?

В этой статье и в этой статье утверждается, что он может не оценивать все выражения, если в этом нет необходимости для определения результата. Это явно не похоже на случай.


До Java 7 -

if(b != null && b.substring(2) != null)

это не будет бросать NPE, потому что b!= null is false и он вернется false там сам. Итак, можем ли мы сказать, что Streams.allMatch не является точным эквивалентом приведенного выше Java фрагмента кода?


Ответы [ 2 ]

4 голосов
/ 11 марта 2020

Это не имеет ничего общего с allMatch, и все, что связано с тем фактом, что все аргументы метода оцениваются перед вызовом этого метода, при любых обстоятельствах. Все аргументы Stream.of, в данном конкретном случае, оцениваются до вызова Stream.of.

Если вы действительно хотите что-то другое, то наиболее близкое к желаемому поведение будет выглядеть как

Stream
  .<Supplier<String>>of(() -> a, () -> b, () -> b.substring(2), () -> c)
  .map(Supplier::get)
  .allMatch(x -> x != null)
1 голос
/ 12 марта 2020

Streams.allMatch не является точным эквивалентом приведенного выше Java фрагмента кода?

Конечно, это не так! Потоки - это совершенно новый способ мышления при обработке данных.

В любом случае, ваша проблема (не связанная с этим) состоит в том, что для любого вызова функции аргументы оцениваются, поэтому вызов of требует оценки b.subString(2), который явно выбрасывает NPE.

Информация, связанная с Java Спецификацией языка (подчеркнул, мое):

15.7.4 Списки аргументов оцениваются слева -to-Right

В вызове метода или конструктора или в выражении создания экземпляра класса выражения аргумента могут появляться в скобках, разделенных запятыми. Каждое выражение аргумента представляется полностью оцененным перед любой частью любого выражения аргумента справа от него.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...