Как правильно использовать Optional?
- Для чего задумывался Optional и какие есть антипаттерны его использования?
- Для чего задумывался Optional, чем orElse отличается от orElseGet и какие есть антипаттерны его использования?
Optional — тип возвращаемого значения «результата может не быть», видимый в сигнатуре. Распаковывают через map, flatMap, filter, orElseGet, orElseThrow, а не isPresent() + get(). Не для полей, параметров и коллекций.
- orElse вычисляет аргумент всегда, orElseGet — лениво
- Optional<List> не нужен — верните пустой список
- Для примитивов — OptionalInt, OptionalLong
А ещё Optional не сериализуем — ещё одна причина не делать его полем
Подробно
Замысел. Метод findById возвращает Optional<User> — вызывающий видит в сигнатуре, что пользователя может не быть, и не забудет обработать этот случай.
Идиоматичное использование:
String city = repo.findById(id)
.map(User::address)
.map(Address::city)
.orElse("неизвестно");
User u = repo.findById(id)
.orElseThrow(() -> new NotFoundException(id));
repo.findById(id).ifPresentOrElse(this::notify, this::log);
Антипаттерны:
if (opt.isPresent()) opt.get()— тот же null-check, только длиннее;- голый
get()— NoSuchElementException вместо NPE (с Java 10 есть честное имяorElseThrow()); - Optional как поле — не сериализуем, лишний объект на экземпляр;
- Optional как параметр — вызывающий всё равно должен создать Optional, проще перегрузка или null-допускающий параметр;
Optional<List<T>>— пустая коллекция уже означает «ничего нет»;orElse(expensive())— дорогое значение вычисляется всегда.
Что хотят услышать
- Назначение: возвращаемое значение.
- Идиоматичные методы.
- Антипаттерны.
Частые ошибки
- isPresent + get.
- Optional в полях JPA-сущностей.
Проверьте себя
Один верный вариант. Подумайте, потом откройте ответ.
Показать варианты и ответ
- ✓Как тип результата; распаковывать через map/orElseGet/orElseThrow, а не get()
- ✗Как тип полей и параметров везде, где значение может быть null
- ✗Всегда вызывать get() сразу после создания
- ✗Оборачивать в Optional любые коллекции
Что спросят дальше
- Чем orElse отличается от orElseGet?
- Почему Optional не заменяет валидацию входных параметров?
- Почему Optional не реализует Serializable?
- Стоит ли возвращать Optional из метода репозитория?
Разбор темы
- Optional: явное отсутствие значения
Зачем Optional, orElse против orElseGet, композиция map/flatMap/filter и антипаттерны использования.
Связанные вопросы
Разбор собеседования с sotto
После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.