Как кокетливо избегать исключений нулевого указателя в Java 8

Java

Статья организована и переведена сзима be.com/posts/2015/…

Скажите, программирование на Java, какое исключение вам больше всего запомнилось, и чтоNullPointerExceptionПустой указатель можно назвать печально известным. Не говорите, что основной программист столкнется, Даже если уровень средний, опытный программист упадет в эту яму на незначительном месте.

Nullцитируемый изобретательTony HoareВ 2009 году он опубликовал заявление с извинениями, заявив, что до сих пор исключение нулевого указателя нанесло предприятиям ущерб на миллиарды долларов.

Вот что сказал Тони Хоар:

Я называю дизайн ссылок Null многомиллиардной ошибкой. В 1965 году я разрабатывал первую полнофункциональную систему на объектно-ориентированном языке (ALGOL W). Мое соображение в то время состояло в том, чтобы убедиться, что все используемые ссылки безопасны, компилятор проверит их автоматически. Тем не менее, я сопротивлялся искушению включить ссылку Null только для того, чтобы упростить ее реализацию. С тех пор это привело к бесчисленным ошибкам, ошибкам и системным сбоям, а также к неизмеримому ущербу для бизнеса.

В этот момент мы должны научиться противостоять этому. Итак, как мы можем предотвратить ненормальные пустые указатели?

Единственный способ сделать это — добавить проверки для объектов, которые могут быть Null. Но проверка Null утомительна и болезненна. Поэтому некоторые относительно новые языки добавляют специальный синтаксис для работы с проверками Null, напримерНулевой оператор объединения.

существуетGroovyилиKotlinТакже известен на таких языках, какElvisоператор.

К сожалению, в старых версиях Java такого синтаксического сахара не было. В этом отношении в Java8 были сделаны улучшения. Поэтому эта статья предназначена специально для ознакомления с тем, как использовать новые функции Java8 для предотвращения записи.NullPointerExceptionслучилось.


★★★Если это руководство поможет вам, перейдите на GitHub Xiaoha, чтобы помочьStarДавай, спасибо! портал★★★


Как усилить проверку объектов Null в Java 8?

В последней статьеРуководство по новым возможностям Java8В нем кратко упоминалось, как пройтиOptionalclass для выполнения нулевой проверки объектов. Далее давайте углубимся в детали:

В бизнес-системах вложение объектов в объекты является распространенным сценарием, как показано в следующем примере кода:

// 最外层对象
class Outer {
    Nested nested;
    Nested getNested() {
        return nested;
    }
}
// 第二层对象
class Nested {
    Inner inner;
    Inner getInner() {
        return inner;
    }
}
// 最底层对象
class Inner {
    String foo;
    String getFoo() {
        return foo;
    }
}

В бизнесе предположим, что нам нужно получитьOuterОбъект базовогоInnerсерединаfooсвойства, мы должны написать кучу ненулевых проверок, чтобы этого не произошлоNullPointerException:

// 繁琐的代码
Outer outer = new Outer();
if (outer != null && outer.nested != null && outer.nested.inner != null) {
    System.out.println(outer.nested.inner.foo);
}

через Опционально

В Java8 у нас есть более элегантное решение, которое заключается в использованииOptionalТо есть мы можем сделать конвейер в одну строчку кодаmapработать. иНулевая проверка автоматически выполняется внутри метода карты.:

Optional.of(new Outer())
    .map(Outer::getNested)
    .map(Nested::getInner)
    .map(Inner::getFoo
    .ifPresent(System.out::println); // 如果不为空,最终输出 foo 的值

Настройте расширенный API с помощью функций поставщика

Вышеупомянутый метод все еще немного многословен, мы можем его использоватьsuppilerфункция для получения окончательного решения:

public static <T> Optional<T> resolve(Supplier<T> resolver) {
    try {
        T result = resolver.get();
        return Optional.ofNullable(result);
    }
    catch (NullPointerException e) {
        // 可能会抛出空指针异常,直接返回一个空的 Optional 对象
        return Optional.empty();
    }
}

используйте вышеуказанноеresolveСпособ восстановления описанного выше ненулевого сегмента кода проверки:

Outer obj = new Outer();
// 直接调用 resolve 方法,内部做空指针的处理
resolve(() -> obj.getNested().getInner().getFoo());
    .ifPresent(System.out::println); // 如果不为空,最终输出 foo 的值

Наконец

Что вам нужно знать, так это то, что два вышеуказанных решения не являются традиционными.nullПроверка производительности настолько эффективна. Но в большинстве бизнес-сценариев вполне целесообразно отказаться от такой небольшой производительности, чтобы облегчить кодирование. Мы не рекомендуем использовать его, если это не сценарий со строгими требованиями к производительности.

Лично, если вы действительно хотите говорить об этой производительности, лучше оптимизировать и оптимизировать sql-выражения, бизнес-логику и т. д.

Публичный аккаунт Сяохи WeChat, высококачественные статьи будут предоставлены как можно скорее, добро пожаловать на внимание