Java 8 Lambda Chaining - обеспечение безопасности типов - PullRequest
0 голосов
/ 31 декабря 2018

Фрагмент 1:

Optional.of(s).map(str -> str).orElse("");

Фрагмент 2:

Optional.of(s).map(str -> str).orElse(Optional.empty());

Фрагмент 3:

Optional.of(s).map(str -> Optional.of(str)).orElse("hello");

Snippet 1 компилируется нормально, но Snippet 2 &Snippet 3 компилировать с ошибками несовместимости типов.Хотя хорошо, что Snippet 2 & Snippet 3 терпит неудачу, я не понимаю, как они оцениваются.Другими словами, я думаю, что мне не хватает некоторых основ с точки зрения того, как сами лямбды связаны или вызваны.Буду признателен, если кто-то может помочь.

Ответы [ 5 ]

0 голосов
/ 01 января 2019

Подпись orElse: public T orElse(T other).Он должен возвращать тот же тип, что и содержимое Optional<T>.Во втором случае, что бы вы присвоили типу возвращаемому значению, String или Optional<String>?

??? value = Optional.of(s).map(str -> str).orElse(Optional.empty()); 

В третьем случае вы делаете прямо противоположное.Фактическое содержание теперь Optional<String>, а orElse возвращает String.

Надеюсь, это поможет.

0 голосов
/ 31 декабря 2018

Тип, возвращаемый map (например, при наведении курсора на map в Eclipse):

  1. Optional<String>
  2. Optional<String>
  3. Optional<Optional<String>>

orElse определяется как public T orElse(T other), что означает, что параметр должен быть T, поэтому:

  1. orElse("") - "" правильно String
  2. orElse(Optional.empty()) - Optional<?> не String
  3. orElse("hello") - "hello" не Optional<String>
0 голосов
/ 31 декабря 2018

Разбивка фрагмента 2:

Optional.of(s)            //Optional<String>
        .map(str -> str)  //Optional<String>
        .orElse(Optional.empty()); //String or Optional<String>?

И фрагмента 3:

Optional.of(s)                        //Optional<String>
        .map(str -> Optional.of(str)) //Optional<Optional<String>>
        .orElse("hello");             //Optional<String> or String? 

Теперь для фрагмента 3 можно использовать flatMap, чтобы избавиться от вложенных опций:

Optional.of(s)                            //Optional<String>
        .flatMap(str -> Optional.of(str)) //Optional<String>
        .orElse("hello");                 //String
0 голосов
/ 31 декабря 2018

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

Другими словами, если у вас есть Optional<T>, вам нужно передать T методу orElse().

В этом случае вы начинаете с Optional<String, а затем получаете Optional<Optional<String>> из него:

Optional.of(s) .map(str -> Optional.of(str)) .orElse("hello");

Если вы передадите str -> str map(...), он скомпилируется.

0 голосов
/ 31 декабря 2018

Фрагмент 1:

Optional.of(s).map(str -> str).orElse("");

Компилируется, поскольку значение по умолчанию, предоставленное для orElse , того же типа, что и значение, которое Optional содержит , т. Е.String.

Фрагмент 2:

Optional.of(s).map(str -> str).orElse(Optional.empty());

не компилируется, потому что после map у вас есть Optional<String>, но затем вы предоставляете Optional<String> в orElse тогда как это должен быть String.

Фрагмент 3:

Optional.of(s).map(str -> Optional.of(str)).orElse("hello");

не компилируется, потому что после map у вас есть Optional<Optional<String>>, но вы передаете String в orElse, тогда как это должно быть Optional<String>.

В заключение orElse объявляется как:

public T orElse (T other)

и задокументировано как:

Возвращает значение, если присутствует, в противном случае возвращает другое.

т.е. orElse в основном говорит "дай мне значениефакультативно содержит, если присутствует, в противном случае принимает значение по умолчанию ", а также то, что T должен быть того же типа, что и значение, которое содержит Optional.

, поэтому, если у вас есть Optional<String, вы должны указать String до orElse, если у вас есть Optional<Integer, то вы должны указать Integer до orElse и т. Д.


С другой стороны, функция map в вашем первом и втором примере фрагментов является излишней, и поэтому вы можете полностью ее опустить.

Всякий раз, когда вы видите, что вы сами вызываете Optional#map с функцией v -> v, это, вероятно, не нужно.

...