Java Необязательная работа orElse не так, как если бы еще

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

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

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

Я просто пытаюсь понять работу по желанию.

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

Ответы

Ответ 1

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

PoJo poJo1=getNullPoJo().orElseGet(() -> getDefaultPoJo());
PoJo poJo2=getLoadedPoJo().orElseGet(() -> getDefaultPoJo());

Ответ 2

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() - это метод, который создает экземпляр по умолчанию при каждом вызове.

Ответ 3

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

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

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