Java Необязательная работа orElse не так, как если бы еще - PullRequest
17 голосов
/ 24 июня 2019

В Необязательном, в то время как метод option.orElse является вызовом, независимо от того, присутствует ли элемент или не выполнена часть orElse, он не ведет себя как условие if else.

В приведенном ниже коде, если вы видите в Случай 1 , выполняются и getNullPoJo, и getDefaultPoJo, поскольку getNullPoJo возвращает пустое значение Необязательно

В Случай 2 , где вы получите Optional с загруженным значением (из getLoadedPoJo), также вы выполняете getDefaultPoJo

Я просто пытаюсь понять работу факультативного. Или Else.

public static void main (String [] a) {
    PoJo poJo1=getNullPoJo().orElse(getDefaultPoJo());//Case 1
    System.out.println("pojo1 Got "+poJo1.getVariable());
    PoJo poJo2=getLoadedPoJo().orElse(getDefaultPoJo());//Case 2
    System.out.println("pojo2 Got "+poJo2.getVariable());
}

private static Optional<PoJo> getNullPoJo() {
    System.out.println("Executing getNullPoJo");
    Optional<PoJo> optional=Optional.empty();
    return optional;
}

private static Optional<PoJo> getLoadedPoJo() {
    System.out.println("Executing getLoadedPoJo");
    PoJo poJo =new PoJo();
    poJo.setVariable("Loaded");
    Optional<PoJo> optional=Optional.of(poJo);
    return optional;
}

private static PoJo getDefaultPoJo() {
    System.out.println("Executing getDefaultPoJo");
    PoJo poJo =new PoJo();
    poJo.setVariable("Default");
    return poJo;
}

Токовый выход:

Выполнение getNullPoJo

Выполнение getDefaultPoJo

pojo1 По умолчанию

Выполнение getLoadedPoJo

Выполнение getDefaultPoJo

pojo2 загружен

Мой ожидаемый результат:

Выполнение getNullPoJo

Выполнение getDefaultPoJo

pojo1 По умолчанию

Выполнение getLoadedPoJo

pojo2 загружен

Я не хочу вызывать getDefaultPoJo в Случай 2

Ответы [ 3 ]

17 голосов
/ 24 июня 2019

Используйте orElseGet(), чтобы избежать оценки getDefaultPoJo(), когда Optional не пусто:

PoJo poJo1=getNullPoJo().orElseGet(() -> getDefaultPoJo());
PoJo poJo2=getLoadedPoJo().orElseGet(() -> getDefaultPoJo());
13 голосов
/ 24 июня 2019
getNullPoJo().orElse(getDefaultPoJo());

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

1) getNullPoJo()
2) r = getDefaultPoJo()
3) orElse(r)  

Чтобы выполнить метод, необходимо оценить его фактические параметры. Для вызова orElse(getDefaultPoJo()) необходимо также вызвать getDefaultPoJo(). Вот почему вы получаете больше, чем ожидали.

Обычно вы увидите

.orElse(null);
.orElse(defaultValue);

, где null и defaultValue - это предопределенные значения, которые не требуют каких-либо вычислений.

С другой стороны, мы пишем

.orElseGet(() -> generateDefaultValue());
.orElseGet(() -> calculateDefaultOutcome());

, где generateDefaultValue и calculateDefaultOutcome - это методы, которые выполняют некоторые вычисления (интенсивные или те, которые мы не хотим выполнять до подходящего момента [ваш случай]).

Сравните

.orElseGet(() -> createDefaultPoJo());
.orElse(DEFAULT_POJO);

, где DEFAULT_POJO - это переменная, инициализированная до вызова этого метода, а createDefaultPoJo() - это метод, который создает экземпляр по умолчанию при каждом вызове.

5 голосов
/ 24 июня 2019

Вывод правильный, Optional.orElse() всегда выполнит else-действие. (выражение, которое вы предоставляете) Используйте orElseGet() - который вызывает функцию только если Optional.isPresent == false - для желаемого результата:

Разница между `Optional.orElse ()` и `Optional.orElseGet ()`

https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html#orElseGet-java.util.function.Supplier-

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