Как с помощью Optional пройти по цепочке nullable объектов и получить вложенное значение либо вернуть ошибку
Что проверяют
Знаете ли вы разницу между map и flatMap у Optional и умеете ли собрать цепочку без единого if (x != null). Следом часто просят объяснить, почему Optional не делают полем класса.
Как отвечать
Покажите цепочку кодом:
String city = Optional.ofNullable(order)
.map(Order::getCustomer)
.map(Customer::getAddress)
.map(Address::getCity)
.orElseThrow(() -> new CityNotFoundException(orderId));Ключевые моменты:
ofNullable, а неof:Optional.of(null)сам бросаетNullPointerException;map: если функция вернулаnull, получится пустойOptional, поэтому цепочка обычных геттеров безопасна;flatMap: нужен, когда геттер уже возвращаетOptional<T>, иначе выйдетOptional<Optional<T>>;orElseThrow(Supplier): бросает ваше исключение. Вариант без аргументов появился в Java 10 и бросаетNoSuchElementException;orElseпротивorElseGet: аргументorElseвычисляется всегда, даже если значение есть, поэтому дорогой дефолт передают черезorElseGet;or(Java 9): подставляет запаснойOptional, например из второго источника, и цепочка продолжается.
Если по ошибке нужно понимать, на каком звене оборвалась цепочка, скажите прямо: Optional эту информацию теряет. Тогда честнее явные проверки с разными сообщениями.
Где спотыкаются
Делают Optional полем или параметром метода. Он задуман как тип возвращаемого значения, не реализует Serializable и добавляет лишний объект. Поле может быть null, а геттер возвращает Optional.ofNullable(field).
Вызывают get() после isPresent(). Это та же проверка на null, только длиннее: лучше выразить её через map, ifPresent или orElseThrow.
Путают map и flatMap, получают вложенный Optional и распаковывают его двумя get().