Я хотел бы знать о значимом использовании опционального orElseGet

Во-первых, позвольте мне уточнить, что это не вопрос «как использовать» или «отличия» этого метода.

У меня есть запрос на поиск одного объекта по идентификатору в БД.

Если этот идентификатор недействителен, объект не будет возвращен, что приведет к ошибке.

Чтобы этого не произошло, я завернул возвращаемый объект в Optional, и проблема была решена.

В этот момент возникла новая проблема.

В контексте извлечения этого объекта я обнаружил, что у меня есть только два варианта.

  1. Поскольку возвращается объект, он используется нормально.

  2. Объект не возвращается, поэтому мы ничего не можем сделать, кроме null или Throw.

Мой возвращаемый объект — UserEntity.

то есть когда я использую значение

UserEntity user = getUser().orElstGet(null);

или

UserEntity user = getUser().orElstThrow(...);

Я не думаю, что есть что-то еще, что можно сделать.

Если объект, который я хотел, не пришел в ответ, пользователь UserEntity; Нет другого объекта, кроме null, который может содержаться в .

Очевидно, что-то не так, или я думаю, что есть более правильное использование.

Вы можете дать мне совет?

Я бы сказал, что orElseThrow - это правильное поведение, если нулевой результат - это то, чего не должно происходить.

Federico klez Culloca 17.05.2022 09:22

Я использую Optional#ifPresent, чтобы перейти к следующему шагу в моем коде, только если я получил значение

Stefan Warminski 17.05.2022 09:22
.orElstGet(null) почти всегда ошибается. null сообщает необязательному, чтобы получить альтернативное значение из нуля, что вызовет исключение нулевого указателя из вашего собственного кода. Возможно, вы имеете в виду .orElse(null), который установит user значение null, если значение не найдено.
ernest_k 17.05.2022 09:23
there is nothing we can do other than null or Throw. ну нет, вы все еще можете вернуть значение по умолчанию, которое не равно нулю. Самым простым примером будет пустая строка.
thinkgruen 17.05.2022 09:31

Похоже, вы думаете, что orElseGetвсегда применим в любой ситуации. Нет, это не так, как и любой другой метод. Похоже, здесь больше подходит orElseThrow, как вы сказали.

Sweeper 17.05.2022 09:38

Смысл использования Optional.orElseGet(Suppler<T> s) заключается в том, что orElseGet() вызывает get() указанное вами Supplier, если Optional содержит null. Поэтому нет никакого смысла указывать null вместо Supplier. Здесь вам нужно либо orElse(), либо orElseThrow().

user207421 17.05.2022 09:48
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
6
70
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Необязательный — это решение на уровне типа для представления необязательных значений вместо пустых ссылок. Так что в идеале, когда вы работаете с необязательным, у вас может быть несколько вариантов, чтобы избежать нулевой проверки. Пример для вашего варианта использования:

getUser().isPresent()

эквивалентно (предположим, что ваш getUser() теперь возвращает пользователя вместо необязательного)

getUser() != null

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

Я склонен делать это следующим образом:

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

Всякий раз, когда я ожидаю, что запрос вернет одну запись или ничего, я называю метод findSomething(...) и заставляю его возвращать Optional<...>.

Метод getSomething(...) может быть реализован на основе метода findSomething(...). Как это:

// Returns an empty Optional if there is no user with the given id
Optional<UserEntity> findUserById(long id) {
    return ...;
}

// Throws an EntityNotFoundException if there is no user with the given id
UserEntity getUserById(long id) {
    return findUserById(id).orElseThrow(
        () -> new EntityNotFoundException("No UserEntity found with id " + id));
}

Возвращает ли необязательный тип null, если он не найден, например {user: null}. Из документации, empty(): возвращает пустой необязательный экземпляр. Я не уверен, что с этим делать.

Enfield li 17.05.2022 09:52

Нет. Optional действительно более безопасная замена null. Вместо null вы должны вернуть пустой Optional и использовать методы класса Optional, чтобы проверить, пуст ли он или содержит значение, и работать с ним. Основное преимущество заключается в том, что он более явный, чем null, поэтому вы не так легко столкнетесь с неожиданными проблемами, такими как NullPointerException.

Jesper 17.05.2022 10:34

Другой способ думать о Optional состоит в том, что это коллекция, которая может содержать не более одного элемента. Например, это как List, который может быть пустым или содержать один элемент. Пустой Optional (точно так же, как и пустой List) — это не то же самое, что null.

Jesper 17.05.2022 10:41
Ответ принят как подходящий

Вы точно не даете достаточного контекста, чтобы дать осмысленный конкретный ответ.

Для пользователей разумное использование может быть

UserEntity user = userRepo.getUser(userId).orElseGet(() -> userRepo.getGuestUser());

Это действительно зависит от варианта использования.

Другие вопросы по теме