1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/wizardforcel-modern-java-zh

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
ch8.md 6.1 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
gitlife-traslator Отправлено 29.11.2024 19:52 2387d6d

Как избежать 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 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/wizardforcel-modern-java-zh.git
git@api.gitlife.ru:oschina-mirror/wizardforcel-modern-java-zh.git
oschina-mirror
wizardforcel-modern-java-zh
wizardforcel-modern-java-zh
master