Получить доступ

Для чего предназначен Optional?

JuniorЛямбды и Stream APIJava >=8
Ещё спрашивают так:
  • Зачем нужен Optional?
  • Как правильно использовать Optional?
  • Можно ли использовать Optional в полях класса?
Коротко

Optional — контейнер «значение или пусто», который явно говорит, что результата может не быть, и заставляет это обработать.

  • Работа: map, filter, orElse, orElseGet, orElseThrow, ifPresent
  • Предназначен для возвращаемых значений, а не для полей и параметров

А ещё optional.get() без проверки — тот же NPE, только под другим названием

Так подсказку видит пользователь sotto на живом собеседовании — за пару секунд, пока вы думаете вслух.

Подробно

Метод, который может ничего не найти, раньше возвращал null — и вызывающий легко забывал проверку, получая NullPointerException в неожиданном месте. Optional<T> делает отсутствие значения частью типа: по сигнатуре Optional<User> findById(long id) сразу видно, что пользователя может не быть.

Обработка без явных проверок:

  • map и flatMap — преобразовать значение, если оно есть;
  • filter — отбросить по условию;
  • orElse(default) — значение по умолчанию (вычисляется всегда);
  • orElseGet(supplier) — значение по умолчанию лениво;
  • orElseThrow() — бросить исключение при отсутствии;
  • ifPresent / ifPresentOrElse — выполнить действие.

Рекомендации: использовать как тип возвращаемого значения; не делать полями класса и параметрами методов; не возвращать null вместо Optional; для коллекций возвращать пустую коллекцию, а не Optional<List>. Для примитивов есть OptionalInt и подобные.

Пример

String city = userRepository.findById(id)
        .map(User::getAddress)
        .map(Address::getCity)
        .orElse("не указан");

User user = userRepository.findById(id)
        .orElseThrow(() -> new NotFoundException("user " + id));

Что хотят услышать

  • Назначение: явно выразить возможное отсутствие значения.
  • Основные методы обработки без get().
  • Где уместен (возвращаемое значение) и где нет (поля, параметры, коллекции).
  • Разница orElse и orElseGet — плюс.

Частые ошибки

  • Вызывать get() без проверки.
  • Использовать Optional как поле сущности.

Проверьте себя

Один верный вариант. Подумайте, потом откройте ответ.

Показать варианты и ответ
  • ✗Ускорить работу с коллекциями
  • ✓Явно выразить возможное отсутствие значения и снизить риск NPE
  • ✗Полностью заменить исключения
  • ✗Сделать поля потокобезопасными

Что спросят дальше

  • Чем orElse отличается от orElseGet?
  • Почему Optional не сериализуют?

Разбор темы

Связанные вопросы

Закрытая бета

Подсказки на собеседовании — в реальном времени

sotto слышит вопрос интервьюера и показывает короткий ответ и план, как в блоке «Коротко». Оставьте контакт — пришлём доступ и промокод.

  • Промокод на 2 часа — сверх пробных 30 минут
  • Программа для Windows — скачать сразу, войти — через Яндекс ID или VK ID
  • Прямая связь с разработчиком: что улучшить — сделаем