Какие преимущества Optional над null в Java
Что проверяют
Понимаете ли вы, для чего Optional задумывался, а не только его методы. Почти всегда следом спрашивают, где его использовать не стоит: в полях, параметрах, коллекциях.
Как отвечать
Optional<T> появился в Java 8 как тип возвращаемого значения для методов, у которых результата может не быть. Главное преимущество: отсутствие значения становится частью сигнатуры. Optional<User> findById(long id) прямо говорит вызывающему, что пользователь может не найтись, и распаковывать результат приходится осознанно.
- явный контракт: про возможный
nullзнает только тот, кто прочитал документацию или код, аOptionalвидно в типе; - цепочки без проверок:
map,flatMap,filter,orElse,orElseGetзаменяют лесенку изif (x != null); - ошибка в нужном месте:
orElseThrow()без аргументов (с Java 10) бросаетNoSuchElementExceptionтам, где значения нет, а неNullPointerExceptionтремя вызовами позже; - связка со стримами:
findFirst,min,maxвозвращаютOptional, а с Java 9 естьOptional.stream(),ifPresentOrElseиor.
Обязательно назовите ограничения, это ценится. Optional не реализует Serializable, поэтому не годится для полей сущностей и DTO. В параметрах метода он усложняет вызов, проще перегрузка. Коллекцию возвращают пустой, а не Optional<List<T>>. Для примитивов есть OptionalInt, OptionalLong, OptionalDouble. Каждый Optional это лишний объект, в горячем цикле это заметно.
Где спотыкаются
Говорят, что Optional избавляет от NullPointerException. Сам по себе нет: переменная типа Optional тоже может оказаться null, а get() на пустом бросает исключение.
Путают orElse и orElseGet. Аргумент в orElse(createDefault()) вычисляется всегда, даже если значение есть, поэтому для дорогого вычисления нужен orElseGet(this::createDefault).
Пишут if (opt.isPresent()) { use(opt.get()); }. Это та же проверка на null, только в обёртке, и смысл теряется. Лучше map, ifPresent или orElseThrow.