Я отметил, что многие методы Java 8 в Oracle JDK используют Objects.requireNonNull()
, который внутренне выдает, NullPointerException
если данный объект (аргумент) есть null
.
public static <T> T requireNonNull(T obj) {
if (obj == null)
throw new NullPointerException();
return obj;
}
Но NullPointerException
будет брошен в любом случае, если null
объект разыменован. Итак, зачем делать эту дополнительную нулевую проверку и бросок
NullPointerException
?
Один очевидный ответ (или преимущество) состоит в том, что он делает код более читабельным, и я согласен. Я хотел бы знать любые другие причины для использования
Objects.requireNonNull()
в начале метода.
java
java-8
nullpointerexception
user4686046
источник
источник
Objects.requireNonNull
, ваш код не имеет разветвлений, поэтому за один проход модульного теста вы получите 100% охват :-)Ответы:
Потому что вы можете сделать вещи явно , делая это. Подобно:
Или короче:
Теперь ты знаешь :
new()
Сравните это с: вы создаете объект Foo сегодня, а завтра вы вызываете метод, который использует это поле и создает его. Скорее всего, завтра вы не узнаете, почему эта ссылка была нулевой вчера, когда она была передана конструктору!
Другими словами: явно используя этот метод для проверки входящих ссылок, вы можете контролировать момент времени, когда будет выдано исключение. И большую часть времени вы хотите провалиться как можно быстрее !
Основными преимуществами являются:
bar
он не равен нулю - и, следовательно, вам не нужны никакиеif (bar == null)
проверки в других местах!источник
this.bar = Objects.requireNonNull(bar, "bar must not be null");
Objects.requireNonNull(bar, "bar must not be null");
. Спасибо за это.this.bar = Objects.requireNonNull(bar, "bar must not be null");
нормально в конструкторах, но потенциально опасно в других методах, если в одном и том же методе установлены две или более переменных. Пример: talkwards.com/2018/11/03/…Fail-быстрый
Код должен вылететь как можно скорее. Он не должен выполнять половину работы, а затем разыменовывать нулевое значение и падать только тогда, когда оставляется половина выполненной работы, в результате чего система находится в недопустимом состоянии.
Это обычно называется «провал рано» или «быстро провал» .
источник
Это означает, что вы обнаружите проблему немедленно и надежно .
Рассматривать:
.NET делает это лучше, отделяя
NullReferenceException
(«вы разыменовали нулевое значение») отArgumentNullException
(«вы не должны были передавать нулевое значение в качестве аргумента - и это было для этого параметра). Я бы хотел, чтобы Java делала то же самое, но даже с простоNullPointerException
, все еще намного легче исправить код, если ошибка генерируется в самой ранней точке, в которой она может быть обнаружена.источник
Использование в
requireNonNull()
качестве первых утверждений в методе позволяет прямо / быстро определить причину исключения.Трассировка стека четко указывает на то, что исключение было сгенерировано сразу после ввода метода, поскольку вызывающая сторона не соблюдала требования / контракт. Передача
null
объекта другому методу может действительно вызывать исключение за один раз, но причина проблемы может быть более сложной для понимания, поскольку исключение будет вызвано определенным вызовомnull
объекта, который может быть намного дальше.Вот конкретный и реальный пример, который показывает, почему мы должны отдавать предпочтение быстрым сбоям в целом и, в частности, используя
Object.requireNonNull()
или каким-либо образом выполнять проверку на нулевое значение для параметров, предназначенных для этогоnull
.Предположим, что
Dictionary
класс , который сочиняетLookupService
иList
изString
представляющих слова , содержащиеся в. Эти поля предназначены для неnull
и один из них передается вDictionary
конструктор.Теперь предположим «плохую» реализацию
Dictionary
безnull
проверки в записи метода (здесь это конструктор):Теперь давайте вызовем
Dictionary
конструктор соnull
ссылкой наwords
параметр:JVM бросает NPE в этом заявлении:
Исключение вызывается в
LookupService
классе, а его происхождение намного раньше (Dictionary
конструктор). Это делает общий анализ проблем гораздо менее очевидным.Есть
words
null
? Естьwords.get(0) null
? Обе ? Почему один, другой или, может быть, обаnull
? Это ошибка кодирования вDictionary
(конструктор? Вызванный метод?)? Это ошибка кодирования вLookupService
? (конструктор? вызванный метод?)?Наконец, нам нужно будет проверить больше кода, чтобы найти источник ошибки, а в более сложном классе, возможно, даже использовать отладчик, чтобы легче понять, что это произошло.
Но почему простая вещь (отсутствие проверки нуля) становится сложной проблемой? Представьте себе, что
Потому что мы допустили начальную ошибку / отсутствие идентифицируемой утечки конкретного компонента на нижних компонентах.
LookupService
Был ли это не локальный сервис, а удаленный сервис или сторонняя библиотека с небольшим количеством отладочной информации, или вы предполагаете, что у вас не было 2, а 4 или 5 уровней вызовов объектов до того, какnull
их обнаружат? Проблема была бы еще более сложной для анализа.Таким образом, способ одолеть это
Таким образом, нет головной боли: мы получаем исключение, как только это получено:
Обратите внимание, что здесь я проиллюстрировал проблему с помощью конструктора, но вызов метода мог иметь такое же ограничение проверки нуля.
источник
Как примечание: этот сбой произошел быстро до того, как
Object#requireNotNull
был реализован немного по-другому до java-9 внутри некоторых классов jre. Предположим, дело:В Java-8 это компилируется как (только соответствующие части)
В основном это операция как:
yourReference.getClass
- которая потерпит неудачу, если ваша ссылка являетсяnull
.Ситуация изменилась в jdk-9, где компилируется тот же код, что и
Или в принципе
Objects.requireNotNull (yourReference)
источник
Основное использование - проверка и бросание
NullPointerException
немедленно.Одна лучшей альтернативой (ярлык) для удовлетворения тех же требований является @NonNull аннотации на Ломбках.
источник
Исключение нулевого указателя выдается при доступе к члену объекта, который находится
null
на более позднем этапе.Objects.requireNonNull()
немедленно проверяет значение и выдает исключение мгновенно, не двигаясь вперед.источник
Я думаю, что это должно использоваться в конструкторах копирования и некоторых других случаях, таких как DI, входной параметр которого является объектом, вы должны проверить, является ли параметр нулевым. В таких обстоятельствах вы можете использовать этот статический метод удобно.
источник
В контексте расширений компилятора, которые реализуют проверку Nullability (например: uber / NullAway ),
Objects.requireNonNull
следует использовать несколько экономно для случаев, когда у вас есть поле Nullable, которое, как вы знаете, не является нулевым в определенной точке вашего кода.Таким образом, есть два основных использования:
Проверка
Маркировка обнуляемости (меняется с @Nullable на @Nonnull)
Пример использования маркировки Nullability:
источник
В дополнение ко всем правильным ответам:
Мы используем его в реактивных потоках. Обычно в результате
NullpointerException
s оборачиваются в другие исключения в зависимости от их появления в потоке. Следовательно, позже мы можем легко решить, как обработать ошибку.Просто пример: представьте, что у вас есть
где
parseAndValidate
оборачиваетNullPointerException
изrequireNonNull
вParsingException
.Теперь вы можете решить, например, когда делать повторную попытку или нет:
Без проверки в
save
методе возникнет исключение NullPointerException , что приведет к бесконечным повторным попыткам. Даже стоит, представьте себе долгую живую подписку, добавивТеперь
RetryExhaustException
будет убить вашу подписку.источник