Какие проверки на null нужно добавлять в цепочке вызовов в Java?
Что проверяют
Не умение написать if (x != null), а понимание, откуда берётся null и где его проверять. Следом обычно спрашивают, когда Optional уместен, а когда это злоупотребление.
Как отвечать
Главный тезис: проверять на границах, а не везде. null приходит из внешнего ввода, JSON, базы, сторонних библиотек, Map.get. Там его ловят или сразу валят с понятной ошибкой через Objects.requireNonNull(value, "value"), например в конструкторе или компактном конструкторе record. Внутри своего кода опирайтесь на контракт.
Для цепочки order.getCustomer().getAddress().getCity() варианты такие:
Optional:Optional.ofNullable(order).map(Order::getCustomer).map(Customer::getAddress).map(Address::getCity).orElse("").mapпревращаетnullна любом шаге в пустойOptional, а если геттер сам возвращаетOptional, нуженflatMap;- перепроектирование: геттеры не возвращают
null. Пустая коллекция вместоnull, значение по умолчанию, Null Object. По закону Деметры цепочку лучше спрятать в метод вродеorder.deliveryCity(); - аннотации:
@Nullableи@NullMarkedиз JSpecify плюс NullAway или инспекции IDE находят пропущенные проверки ещё до запуска.
Правила для Optional: только как возвращаемое значение, не в полях, параметрах и коллекциях. get() без проверки бросает NoSuchElementException, это та же ошибка в другой обёртке. orElse вычисляет аргумент всегда, orElseGet лениво.
Упомяните helpful NullPointerExceptions: начиная с Java 15 сообщение по умолчанию называет звено цепочки, которое вернуло null, например because the return value of "Customer.getAddress()" is null.
Где спотыкаются
Проверяют всё подряд и молча возвращают null дальше. Ошибка всплывает далеко от причины, и найти её сложнее, чем при падении сразу.
Оборачивают в Optional поля и параметры или пишут Optional.ofNullable(x).isPresent() как многословную замену x != null.
Возвращают null вместо пустого списка или ловят NullPointerException в catch, чтобы управлять логикой. Это прячет баги, а не решает их.