Как избежать NullPointerException в Java 8
Как избежать печально известного исключения NullPointerException в Java? Это один из ключевых вопросов, который рано или поздно задаёт себе каждый начинающий Java-разработчик. И опытные программисты среднего и высокого уровня постоянно избегают этой ошибки. На сегодняшний день это одна из самых распространённых ошибок не только в Java, но и во многих других языках программирования.
Тони Хоар, создатель Null, в 2009 году извинился за свою ошибку и назвал её ошибкой на миллиард долларов.
«Я назову его своей ошибкой на миллиард долларов. Она была изобретена в 1965 году, когда я разработал первый всеобъемлющий ссылочный тип в ALGOL W. Моей целью было обеспечить абсолютную безопасность использования всех ссылок, а компилятор автоматически выполнял бы проверку. Но я не смог устоять перед соблазном и добавил Null-ссылку, просто потому что это было легко реализовать. Это привело к бесчисленным ошибкам, уязвимостям и сбоям системы, которые, возможно, стоили миллиарды долларов за последующие 40 лет».
Тем не менее мы должны с этим столкнуться. Итак, что же мы можем сделать, чтобы предотвратить исключение NullPointerException? Ответ очевиден: добавить проверку на null. Поскольку проверка на null всё ещё довольно утомительна и болезненна, многие языки добавили специальную синтаксическую конструкцию для обработки проверки на null, известную как оператор объединения с null (или оператор Элвиса) — в таких языках, как Groovy или Kotlin.
К сожалению, Java не предоставляет такой синтаксической конструкции. Однако, к счастью, ситуация улучшилась в Java 8. В этой статье представлены несколько методов, использующих новые функции Java 8, такие как лямбда-выражения, для предотвращения ненужной проверки на null.
Повышение безопасности при работе с Null в Java 8
В другой статье я объяснил, как использовать тип Optional в Java 8 для предотвращения проверки на null. Вот пример кода из этой статьи.
Предположим, у нас есть такая иерархия классов:
class Outer {
Nested nested;
Nested getNested() {
return nested;
}
}
class Nested {
Inner inner;
Inner getInner() {
return inner;
}
}
class Inner {
String foo;
String getFoo() {
return foo;
}
}
Решить проблему глубокого вложения путей в этой структуре может быть немного сложно. Мы должны написать множество проверок на null, чтобы убедиться, что они не вызывают исключение NullPointerException:
Outer outer = new Outer();
if (outer != null && outer.nested != null && outer.nested.inner != null) {
System.out.println(outer.nested.inner.foo);
}
Мы можем избавиться от всех этих проверок на null, используя тип Optional в Java 8. Метод map принимает лямбда-выражение типа Function и автоматически упаковывает результат каждой функции в объект Optional. Это позволяет нам выполнять несколько операций map в одной строке. Проверка на null выполняется автоматически на нижнем уровне.
Optional.of(new Outer())
.map(Outer::getNested)
.map(Nested::getInner)
.map(Inner::getFoo)
.ifPresent(System.out::println);
Другой способ решить проблему вложенного пути — использовать функцию поставщика:
Outer obj = new Outer();
resolve(() -> obj.getNested().getInner().getFoo());
.ifPresent(System.out::println);
Вызов obj.getNested().getInner().getFoo() может вызвать исключение NullPointerException. В этом случае исключение будет перехвачено, и метод вернёт Optional.empty().
public static <T> Optional<T> resolve(Supplier<T> resolver) {
try {
T result = resolver.get();
return Optional.ofNullable(result);
}
catch (NullPointerException e) {
return Optional.empty();
}
}
Помните, что эти два решения могут не иметь такой высокой производительности, как традиционные проверки на null. Однако в большинстве случаев это не должно вызывать серьёзных проблем.
Как обычно, примеры кода можно найти на GitHub.
Счастливого программирования!
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )