Я object != null
много использую, чтобы избежать NullPointerException
.
Есть ли хорошая альтернатива этому?
Например, я часто использую:
if (someobject != null) {
someobject.doCalc();
}
Это проверка для а NullPointerException
для someobject
объекта в приведенном выше фрагменте кода.
Обратите внимание, что принятый ответ может быть устаревшим, см. Https://stackoverflow.com/a/2386013/12943 для более недавнего подхода.
java
object
nullpointerexception
null
Goran Martinic
источник
источник
Option
тип Scala омрачен нежеланием языка контролировать или запрещатьnull
. Я упомянул об этом в hackernews, получил отрицательное голосование и сказал, что "в любом случае в Scala никто не использует null". Угадайте что, я уже нахожу нули в написанном сотрудником Scala. Да, они «делают это неправильно» и должны быть осведомлены об этом, но факт остается фактом: система типов языка должна защищать меня от этого, а это не так :(Ответы:
Для меня это звучит как довольно распространенная проблема, с которой, как правило, сталкиваются младшие и средние разработчики: они либо не знают, либо не доверяют контрактам, в которых они участвуют, и защищают от нуля. Кроме того, при написании собственного кода они, как правило, полагаются на возврат значений NULL для указания чего-либо, что требует от вызывающей стороны проверки на наличие значений NULL.
Другими словами, есть два случая, когда возникает проверка нуля:
Где ноль является действительным ответом с точки зрения договора; а также
Где это не правильный ответ.
(2) легко. Либо используйте
assert
операторы (утверждения), либо разрешите ошибку (например, NullPointerException ). Утверждения - это сильно недоиспользуемая функция Java, которая была добавлена в 1.4. Синтаксис:или
где
<condition>
- логическое выражение и<object>
является объектом, чейtoString()
вывод метода будет включен в ошибку.assert
Заявление бросаетError
(AssertionError
) , если условие не выполняется. По умолчанию Java игнорирует утверждения. Вы можете включить утверждения, передав опцию-ea
JVM. Вы можете включать и отключать утверждения для отдельных классов и пакетов. Это означает, что вы можете проверять код с помощью утверждений при разработке и тестировании, а также отключать их в производственной среде, хотя мое тестирование показало, что утверждения не влияют практически на производительность.Не использовать утверждения в этом случае - это нормально, потому что код просто потерпит неудачу, что произойдет, если вы используете утверждения. Единственное отличие состоит в том, что с утверждениями это может произойти раньше, более значимым образом и, возможно, с дополнительной информацией, которая может помочь вам понять, почему это произошло, если вы не ожидали этого.
(1) немного сложнее. Если у вас нет контроля над кодом, который вы вызываете, вы застряли. Если ноль является действительным ответом, вы должны проверить его.
Если это код, который вы контролируете, однако (и это часто бывает), то это другая история. Избегайте использования нулей в качестве ответа. С методами, которые возвращают коллекции, это легко: возвращать пустые коллекции (или массивы) вместо нулей почти все время.
С не-коллекциями это может быть сложнее. Рассмотрим это в качестве примера: если у вас есть эти интерфейсы:
где Parser принимает необработанный пользовательский ввод и находит что-то, возможно, если вы реализуете интерфейс командной строки для чего-то. Теперь вы можете заключить договор, который возвращает ноль, если нет соответствующих действий. Это приводит к нулевой проверке, о которой вы говорите.
Альтернативное решение состоит в том, чтобы никогда не возвращать нуль и вместо этого использовать шаблон Null Object :
Для сравнения:
в
это намного лучший дизайн, потому что это приводит к более лаконичному коду.
Тем не менее, возможно, для метода findAction () вполне уместно выдать исключение со значимым сообщением об ошибке, особенно в том случае, когда вы полагаетесь на пользовательский ввод. Было бы гораздо лучше, чтобы метод findAction выдавал исключение, чем вызывающий метод взорвался простой NullPointerException без объяснения причин.
Или, если вы думаете, что механизм try / catch слишком уродлив, вместо «Ничего не делать», ваше действие по умолчанию должно предоставить обратную связь пользователю.
источник
Если вы используете (или планируете использовать) Java IDE, такую как JetBrains IntelliJ IDEA , Eclipse или Netbeans, или инструмент, подобный findbugs, то вы можете использовать аннотации для решения этой проблемы.
По сути, у вас есть
@Nullable
и@NotNull
.Вы можете использовать в методе и параметрах, как это:
или
Второй пример не скомпилируется (в IntelliJ IDEA).
Когда вы используете первую
helloWorld()
функцию в другом фрагменте кода:Теперь компилятор IntelliJ IDEA скажет вам, что проверка бесполезна, поскольку
helloWorld()
функцияnull
никогда не вернется .Используя параметр
если вы напишите что-то вроде:
Это не скомпилируется.
Последний пример использования
@Nullable
Делая это
И вы можете быть уверены, что этого не произойдет. :)
Это хороший способ позволить компилятору проверить что-то большее, чем обычно, и заставить ваши контракты быть сильнее. К сожалению, это поддерживается не всеми компиляторами.
В IntelliJ IDEA 10.5 и далее добавлена поддержка любых других
@Nullable
@NotNull
реализаций.Смотрите сообщение в блоге. Более гибкие и настраиваемые аннотации @ Nullable / @ NotNull .
источник
@NotNull
,@Nullable
И другое nullness аннотации является частью JSR 305 . Вы также можете использовать их для обнаружения потенциальных проблем с такими инструментами, как FindBugs .@NotNull
&@Nullable
живут в пакетеcom.sun.istack.internal
. (Думаю, я связываю com.sun с предупреждениями об использовании проприетарного API.)@NotNull
и@Nullable
являются в том , что они прекрасно деградировать , когда исходный код строятся с помощью системы , которая не понимает их. Таким образом, фактически аргумент, что код не является переносимым, может быть недопустимым - если вы используете систему, которая поддерживает и понимает эти аннотации, вы получаете дополнительное преимущество более строгой проверки ошибок, в противном случае вы получаете меньше ее, но ваш код все равно должен сборка в порядке, и качество вашей работающей программы ТО ЖЕ, потому что эти аннотации не были применены во время выполнения в любом случае. Кроме того, все компиляторы пользовательские ;-)Если нулевые значения не разрешены
Если ваш метод вызывается извне, начните с чего-то вроде этого:
Затем, в остальной части этого метода, вы будете знать, что
object
это не нуль.Если это внутренний метод (не часть API), просто документируйте, что он не может быть нулевым, и все.
Пример:
Однако, если ваш метод просто передает значение, а следующий метод передает его и т. Д., Это может стать проблематичным. В этом случае вы можете проверить аргумент, как указано выше.
Если ноль разрешен
Это действительно зависит. Если обнаружите, что я часто делаю что-то вроде этого:
Поэтому я делаю ветки и делаю две совершенно разные вещи. Там нет отвратительного фрагмента кода, потому что мне действительно нужно сделать две разные вещи в зависимости от данных. Например, я должен работать на входе, или я должен рассчитать хорошее значение по умолчанию?
На самом деле я редко использую идиому "
if (object != null && ...
".Возможно, вам будет легче привести примеры, если вы покажете примеры того, где вы обычно используете идиому.
источник
throw new IllegalArgumentException("object==null")
Ничего себе, я почти не хочу добавлять другой ответ, когда у нас есть 57 различных способов рекомендовать
NullObject pattern
, но я думаю, что некоторые люди, заинтересованные в этом вопросе, могли бы знать, что на столе есть предложение для Java 7, чтобы добавить "нулевой безопасный обработка " - упрощенный синтаксис для логики if-not-equal-null.Пример, приведенный Алексом Миллером, выглядит следующим образом:
Эти
?.
средства только де-ссылки на левый идентификатор , если он не является нулевым, в противном случае оценка оставшейся части выражения , какnull
. Некоторым людям, таким как член Java Posse Дик Уолл и избиратели в Devoxx, действительно нравится это предложение, но есть и оппозиция на том основании, что оно будет поощрять более широкое использованиеnull
в качестве дозорной ценности.Обновление: официальное предложение по нулевому безопасному оператору в Java 7 было представлено в рамках проекта Coin. Синтаксис немного отличается от приведенного выше примера, но это то же самое понятие.
Обновление: предложение нулевого безопасного оператора не попало в Project Coin. Таким образом, вы не увидите этот синтаксис в Java 7.
источник
Если неопределенные значения не разрешены:
Вы можете настроить свою среду IDE так, чтобы она предупреждала вас о возможной нулевой разыменованию. Например, в Eclipse см. Настройки> Java> Компилятор> Ошибки / Предупреждения / Нулевой анализ .
Если допустимы неопределенные значения:
Если вы хотите определить новый API, в котором неопределенные значения имеют смысл , используйте шаблон параметров (может быть знаком по функциональным языкам). Имеет следующие преимущества:
Java 8 имеет встроенный
Optional
класс (рекомендуется); для более ранних версий, есть библиотека альтернативы, например гуавы «sOptional
или FunctionalJava » sOption
. Но, как и во многих шаблонах в функциональном стиле, использование Option в Java (даже 8) приводит к некоторому шаблону, который можно сократить, используя менее подробный язык JVM, например Scala или Xtend.Если вам приходится иметь дело с API, который может возвращать нули , вы не можете сделать многое в Java. Xtend и Groovy имеют оператор Элвиса
?:
и нулевой безопасный оператор разыменования?.
, но обратите внимание, что в случае нулевой ссылки это возвращает нуль, поэтому он просто «откладывает» правильную обработку нулевого значения.источник
Только для этой ситуации -
Не проверять, является ли переменная нулевой, прежде чем вызывать метод equals (пример сравнения строк ниже):
приведет к
NullPointerException
еслиfoo
не существует.Вы можете избежать этого, если вы сравните свои
String
вот так:источник
<object that you know that is not null>.equals(<object that might be null>);
. Он работает для других методов, кроме техequals
, которые известны контракту, и эти методы могут обрабатыватьnull
параметры.С Java 8 приходит новое
java.util.Optional
класс, который, возможно, решает некоторые проблемы. Можно, по крайней мере, сказать, что это улучшает читабельность кода, а в случае открытых API-интерфейсов делает контракт API-интерфейса более понятным для разработчика клиента.Они работают так:
Необязательный объект для данного типа (
Fruit
) создается как тип возврата метода. Может быть пустым или содержатьFruit
объект:Теперь посмотрите на этот код, где мы ищем список
Fruit
(fruits
) для данного экземпляра Fruit:Вы можете использовать
map()
оператор для выполнения вычисления или извлечения значения из необязательного объекта.orElse()
позволяет вам предоставить запасной вариант для пропущенных значений.Конечно, проверка на нулевое / пустое значение все еще необходима, но, по крайней мере, разработчик осознает, что значение может быть пустым, и риск забыть проверить ограничен.
В API, построенном с нуля, используется
Optional
всякий раз, когда возвращаемое значение может быть пустым, и возвращает простой объект только тогда, когда это невозможноnull
(соглашение), клиентский код может отказаться от нулевых проверок возвращаемых значений простых объектов ...Конечно,
Optional
можно также использовать в качестве аргумента метода, возможно, лучший способ указать необязательные аргументы, чем 5 или 10 методов перегрузки в некоторых случаях.Optional
предлагает другие удобные методы, например,orElse
которые позволяют использовать значение по умолчанию, иifPresent
которые работают с лямбда-выражениями .Я приглашаю вас прочитать эту статью (мой основной источник для написания этого ответа), в которой
NullPointerException
хорошо (как и вообще нулевой указатель) проблематично, а также (частично) приведенное решениеOptional
хорошо объяснено: Необязательные объекты Java .источник
if(optional.isPresent()){ optional.get(); }
вместоoptional.ifPresent(o -> { ...})
В зависимости от того, какие объекты вы проверяете, вы можете использовать некоторые классы в общих фондах apache, такие как: apache commons lang и apache commons collection
Пример:
или (в зависимости от того, что вам нужно проверить):
Класс StringUtils - только один из многих; Есть много хороших классов в общем достоянии, которые делают нулевую безопасную манипуляцию.
Ниже приведен пример того, как вы можете использовать null vallidation в JAVA при включении библиотеки apache (commons-lang-2.4.jar)
И если вы используете Spring, Spring также имеет те же функции в своем пакете, см. Библиотеку (spring-2.4.6.jar)
Пример того, как использовать этот статический класс из весны (org.springframework.util.Assert)
источник
Вы должны проверять объект! = Null, только если вы хотите обработать случай, когда объект может быть нулевым ...
Есть предложение добавить новые аннотации в Java7, чтобы помочь с пустыми / ненулевыми параметрами: http://tech.puredanger.com/java7/#jsr308
источник
Я фанат кода "быстро проваливаюсь". Спросите себя - вы делаете что-то полезное в случае, когда параметр имеет значение null? Если у вас нет четкого ответа о том, что ваш код должен делать в этом случае ... Т.е. он никогда не должен быть нулевым, а затем игнорировать его и разрешать исключение NullPointerException. Вызывающий код будет иметь столько же смысла для NPE, сколько и IllegalArgumentException, но разработчику будет легче отлаживать и понимать, что пошло не так, если выбрасывается NPE, а не ваш код, пытающийся выполнить какое-то другое непредвиденное непредвиденное обстоятельство. логика - что в конечном итоге приводит к сбою приложения в любом случае.
источник
Каркас коллекций Google предлагает хороший и элегантный способ выполнить нулевую проверку.
В классе библиотеки есть такой метод:
И использование (с
import static
):Или в вашем примере:
источник
getThing().getItsThing().getOtherThing().wowEncapsulationIsBroken().setLol("hi");
Иногда у вас есть методы, которые работают с его параметрами, которые определяют симметричную операцию:
Если вы знаете, что b никогда не может быть нулевым, вы можете просто поменять его местами. Это наиболее полезно для равных:
foo.equals("bar");
лучше не делать"bar".equals(foo);
.источник
equals
(может быть любой метод) будет обрабатывать ноль правильно. На самом деле все, что это делает - передает ответственность кому-то другому (или другому методу).equals
(или любой другой метод) должен проверить вnull
любом случае. Или прямо заявите, что это не так.Вместо шаблона нулевого объекта - который имеет свои применения - вы можете рассмотреть ситуации, когда нулевой объект является ошибкой.
Когда выдается исключение, изучите трассировку стека и проработайте ошибку.
источник
Нуль не является «проблемой». Это неотъемлемая часть полного набора инструментов моделирования. Программное обеспечение стремится моделировать сложность мира и ноль несет свое бремя. Нуль означает «Нет данных» или «Неизвестно» в Java и тому подобное. Поэтому для этих целей целесообразно использовать нули. Я не предпочитаю шаблон «Нулевой объект»; Я думаю, что это поднимает проблему « кто будет охранять стражей ».
Если вы спросите меня, как зовут мою подругу, я скажу вам, что у меня нет подруги. На языке Java я верну ноль. Альтернативой может быть выбрасывание значимого исключения, чтобы указать на проблему, которая не может быть (или не
Для «неизвестного вопроса» дайте «неизвестный ответ». (Будьте безопасны с нулевым значением, если это правильно с деловой точки зрения) Проверка аргументов на нулевое значение один раз внутри метода перед использованием освобождает нескольких вызывающих от проверки их перед вызовом.
Предыдущее приводит к нормальной логике, чтобы не получить фотографию несуществующей девушки из моей библиотеки фотографий.
И это подходит с новым Java API (с нетерпением жду)
Хотя для некоторых людей это довольно «обычный бизнес-процесс» - не найти фотографии, хранящиеся в БД, но в некоторых других случаях я использовал пары, подобные приведенным ниже.
И не надо набирать
<alt> + <shift> + <j>
текст (генерировать javadoc в Eclipse) и написать три дополнительных слова для вашего публичного API. Этого будет более чем достаточно для всех, кроме тех, кто не читает документацию.или
Это довольно теоретический случай, и в большинстве случаев вам следует предпочесть java нуль-безопасный API (в случае, если он будет выпущен через 10 лет), но
NullPointerException
это подкласс классаException
. Таким образом, это форма,Throwable
которая указывает условия, которые разумное приложение может захотеть поймать ( javadoc )! Использовать первое наибольшее преимущество исключений и отделить код обработки ошибок от «обычного» кода ( по словам создателей Java ), уместно, на мой взгляд, пойматьNullPointerException
.Могут возникнуть вопросы:
Q. Что делать, если
getPhotoDataSource()
возвращает ноль?О. Это зависит от бизнес-логики. Если я не смогу найти фотоальбом, я не покажу вам фотографий. Что если appContext не инициализирован? Бизнес-логика этого метода мирится с этим. Если та же логика должна быть более строгой, чем генерирование исключения, это является частью бизнес-логики, и следует использовать явную проверку на нулевое значение (случай 3). новых Java Null-безопасный API припадки лучше здесь , чтобы указать выборочно , что подразумевает и то , что не означает быть инициализирован , чтобы быть не в состоянии , быстро в случае ошибок программиста.
Q. Избыточный код может быть выполнен и ненужные ресурсы могут быть захвачены.
О. Это могло бы иметь место, если
getPhotoByName()
быPreparedStatement
в конце концов попытался открыть соединение с базой данных, создать и использовать имя человека в качестве параметра SQL. Подход к неизвестному вопросу дает неизвестный ответ (случай 1) работает здесь. Перед захватом ресурсов метод должен проверить параметры и, если необходимо, вернуть «неизвестный» результат.Q. Этот подход имеет снижение производительности из-за открытия попытки закрытия.
О. Программное обеспечение должно быть простым для понимания и изменения в первую очередь. Только после этого можно думать о производительности и только при необходимости! и где нужно! ( источник ) и многие другие).
PS. Этот подход будет настолько же разумным, чтобы использовать его, поскольку отдельный код обработки ошибок от принципа «обычного» кода целесообразно использовать в некоторых местах. Рассмотрим следующий пример:
PPS. Для тех, кто быстро понижает голос (и не так быстро читает документацию), я хотел бы сказать, что я никогда не ловил исключение с нулевым указателем (NPE) в своей жизни. Но эта возможность была специально разработана создателями Java, потому что NPE является подклассом
Exception
. У нас есть прецедент в истории Java, когдаThreadDeath
это происходитError
не потому, что это на самом деле ошибка приложения, а исключительно потому, что она не была предназначена для перехвата! Сколько NPE подходит, чтобы бытьError
чемThreadDeath
! Но это не так.Проверяйте «Нет данных», только если это подразумевает бизнес-логика.
а также
Если appContext или dataSource не инициализирован, необработанная среда выполнения NullPointerException уничтожит текущий поток и будет обработана Thread.defaultUncaughtExceptionHandler (для вас, чтобы определить и использовать ваш любимый регистратор или другой механизм уведомлений). Если не установлено, ThreadGroup # uncaughtException выведет трассировку стека в системную ошибку. Необходимо следить за журналом ошибок приложения и открывать проблему Jira для каждого необработанного исключения, которое фактически является ошибкой приложения. Программист должен исправить ошибку где-то в инициализации.
источник
NullPointerException
и возвращатьnull
ужасно для отладки. В конце концов, вы все равно получите NPE, и очень трудно понять, что изначально было нулевым.if (maybeNull.hasValue()) {...}
так в чем же разницаif (maybeNull != null)) {...}
?Maybe<T>
илиOptional<T>
нет в случае, когда вашT
может быть нулевым, но в случае, когда он никогда не должен быть нулевым. Если у вас есть тип, который явно означает «это значение может быть нулевым, используйте его с осторожностью», и вы используете и возвращаете такой тип последовательно, тогда всякий раз, когда вы видите старыйT
код в своем коде, вы можете предположить, что он никогда не будет нулевым. (Конечно, это было бы намного полезнее, если бы оно могло быть реализовано компилятором.)В Java 7 появился новый
java.util.Objects
служебный класс, в котором естьrequireNonNull()
метод. Все, что он делает - это бросает a,NullPointerException
если его аргумент равен нулю, но он немного очищает код. Пример:Этот метод наиболее полезен для проверки непосредственно перед присваиванием в конструкторе, где при каждом его использовании можно сохранить три строки кода:
становится
источник
doCalc(someObject)
.doCalc()
, и он не бросает NPE сразу, когда ему дано значение NULL, вам нужно будет проверить NULL и бросить NPE самостоятельно. Вот для чегоObjects.requireNonNull()
.В конечном счете, единственный способ полностью решить эту проблему - использовать другой язык программирования:
nil
, и абсолютно ничего не произойдет. Это делает ненужными большинство нулевых проверок, но может значительно усложнить диагностику ошибок.источник
Действительно распространенная «проблема» в Java.
Сначала мои мысли по этому поводу:
Я считаю, что плохо «есть» что-то, когда передается NULL, где NULL не является допустимым значением. Если вы не выходите из метода с какой-либо ошибкой, это означает, что в вашем методе ничего не пошло не так, что неверно. Тогда вы, вероятно, вернете нуль в этом случае, а в методе получения вы снова проверяете на ноль, и он никогда не заканчивается, и в итоге вы получаете «if! = Null» и т. Д.
Итак, IMHO, null должен быть критической ошибкой, которая препятствует дальнейшему выполнению (то есть, когда null не является допустимым значением).
Я решаю эту проблему так:
Во-первых, я следую этому соглашению:
И, наконец, в коде первая строка открытого метода выглядит следующим образом:
Обратите внимание, что addParam () возвращает self, так что вы можете добавить больше параметров для проверки.
Метод
validate()
выбрасывает проверенный,ValidationException
если какой-либо из параметров является нулем (проверенный или непроверенный - больше проблема дизайна / вкуса, но мойValidationException
проверен).Сообщение будет содержать следующий текст, если, например, «plans »пусто:
« Недопустимое значение аргумента null для параметра [планы] »
Как вы можете видеть, второе значение в методе (строке) addParam () необходимо для пользовательского сообщения, потому что вы не можете легко определить переданное имя переменной, даже с отражением (в любом случае это не тема этого сообщения ...).
И да, мы знаем, что за этой строкой мы больше не встретим нулевое значение, поэтому мы просто безопасно вызываем методы для этих объектов.
Таким образом, код является чистым, легко обслуживаемым и читаемым.
источник
Задавая этот вопрос, вы обнаружите, что вас могут заинтересовать стратегии обработки ошибок. Архитектор вашей команды должен решить, как работать с ошибками. Есть несколько способов сделать это:
Позвольте Исключениям проходить сквозь - поймайте их в «главном цикле» или в какой-либо другой управляющей подпрограмме.
Конечно, взгляните также на Аспектно-ориентированное программирование - у них есть аккуратные способы вставки
if( o == null ) handleNull()
в ваш байт-код.источник
В дополнение к использованию
assert
вы можете использовать следующее:Это немного лучше чем:
источник
if (!something) { x(); } else { y(); }
я был бы склонен рефакторинг какif (something) { y(); } else { x(); }
(хотя можно утверждать, что!= null
это более позитивный вариант ...). Но что еще более важно, важная часть кода не обернута внутри{}
s, и у вас на один уровень меньше отступов для большей части метода. Я не знаю, было ли это рассуждением fastcodejava, но это было бы моим.Просто никогда не используйте нуль. Не позволяй это.
В моих классах большинство полей и локальных переменных имеют ненулевые значения по умолчанию, и я добавляю операторы контракта (всегда включенные утверждения) повсюду в коде, чтобы убедиться, что это применяется принудительно (так как оно более лаконично и более выразительно, чем позволяет ему) придумать как NPE, а затем необходимо решить номер строки и т. д.).
Как только я принял эту практику, я заметил, что проблемы, похоже, решаются сами собой. Вы поймете вещи намного раньше в процессе разработки просто случайно и поймете, что у вас есть слабое место ... и что еще более важно ... это помогает инкапсулировать проблемы разных модулей, разные модули могут "доверять" друг другу и больше не засорять код с
if = null else
конструкциями!Это защитное программирование, и в конечном итоге код получается намного чище. Всегда дезинфицируйте данные, например, здесь, применяя жесткие стандарты, и проблемы исчезают.
Контракты похожи на мини-юнит-тесты, которые всегда работают, даже в производстве, и когда что-то не получается, вы знаете почему, а не случайный NPE, который вы должны каким-то образом выяснить.
источник
Guava, очень полезная базовая библиотека от Google, имеет приятный и полезный API, чтобы избежать нулевых значений. Я нахожу с помощью AndAvoidingNullExplained очень полезным.
Как объяснено в вики:
Применение:
источник
Это очень распространенная проблема для каждого разработчика Java. Так что в Java 8 есть официальная поддержка для решения этих проблем без загроможденного кода.
Java 8 представила
java.util.Optional<T>
. Это контейнер, который может содержать или не содержать ненулевое значение. Java 8 предоставила более безопасный способ обработки объекта, значение которого может быть нулевым в некоторых случаях. Он вдохновлен идеями Хаскелла и Скалы .В двух словах, в классе Optional есть методы для явного обращения со случаями, когда значение присутствует или отсутствует. Однако преимущество по сравнению с нулевыми ссылками заключается в том, что дополнительный класс <T> заставляет задуматься о случае, когда значение отсутствует. Как следствие, вы можете предотвратить непреднамеренные исключения нулевого указателя.
В приведенном выше примере у нас есть фабрика обслуживания на дому, которая возвращает дескриптор для нескольких бытовых приборов, доступных в доме. Но эти услуги могут быть или не быть доступными / функциональными; это означает, что это может привести к NullPointerException. Вместо добавления нуля
if
условия перед использованием какого-либо сервиса, давайте поместим его в Optional <Service>.ОБРАЩАЯСЬ К ВАРИАНТУ <T>
Давайте рассмотрим метод, чтобы получить ссылку на сервис с фабрики. Вместо того, чтобы возвращать сервисную ссылку, оберните ее необязательно. Это позволяет пользователю API знать, что возвращенный сервис может или не может быть доступен / функционировать, использовать для защиты
Как видите,
Optional.ofNullable()
обеспечивает простой способ обернуть ссылку. Есть и другие способы получить ссылку на Optional, либоOptional.empty()
&Optional.of()
. Один для возврата пустого объекта вместо перенастройки null, а другой для переноса ненулевого объекта соответственно.ТАК КАК ТОЧНО ЭТО ПОМОГАЕТ ИЗБЕЖАТЬ ПУСТОЙ ПРОВЕРКИ?
После того, как вы обернули ссылочный объект, Optional предоставляет много полезных методов для вызова методов с обернутой ссылкой без NPE.
Optional.ifPresent вызывает данного Потребителя со ссылкой, если это ненулевое значение. В противном случае это ничего не делает.
Представляет операцию, которая принимает один входной аргумент и не возвращает результата. В отличие от большинства других функциональных интерфейсов, ожидается, что потребитель будет работать через побочные эффекты. Это так чисто и легко понять. В приведенном выше примере кода
HomeService.switchOn(Service)
вызывается, если необязательная ссылка удержания не равна нулю.Мы очень часто используем троичный оператор для проверки нулевого условия и возвращаем альтернативное значение или значение по умолчанию. Необязательно предоставляет другой способ обработки того же условия без проверки нулевого значения. Optional.orElse (defaultObj) возвращает defaultObj, если Optional имеет нулевое значение. Давайте использовать это в нашем примере кода:
Теперь HomeServices.get () делает то же самое, но лучше. Проверяет, инициализирован ли сервис или нет. Если это так, верните то же самое или создайте новый новый сервис. Необязательный <T> .orElse (T) помогает вернуть значение по умолчанию.
Наконец, вот наш NPE, а также нулевой код без проверки:
Полный пост - NPE, а также пустой код без проверки ... Правда? ,
источник
if(homeServices != null) {
которую можно изменить наhomeServices.ifPresent(h -> //action)
;Мне нравятся статьи от Nat Pryce. Вот ссылки:
В статьях также есть ссылка на Git-репозиторий для Java Maybe Type, который я нахожу интересным, но я не думаю, что он сам по себе может уменьшить раздувание проверяющего кода. После некоторых исследований в Интернете, я думаю ! = Раздувание нулевого кода может быть уменьшено в основном благодаря тщательному дизайну.
источник
Я пробовал,
NullObjectPattern
но для меня это не всегда лучший путь. Бывают случаи, когда «никаких действий» не уместно.NullPointerException
это исключение времени выполнения, которое означает, что это ошибка разработчиков, и, имея достаточный опыт, она точно скажет, где находится ошибка.Теперь к ответу:
Постарайтесь сделать все свои атрибуты и их методы доступа максимально конфиденциальными или вообще не показывать их клиентам. Конечно, вы можете иметь значения аргумента в конструкторе, но, уменьшая область действия, вы не позволяете клиентскому классу передавать недопустимое значение. Если вам нужно изменить значения, вы всегда можете создать новое
object
. Вы проверяете значения в конструкторе только один раз, а в остальных методах вы можете быть почти уверены, что значения не равны NULL.Конечно, опыт - лучший способ понять и применить это предложение.
Байт!
источник
Вероятно, лучшая альтернатива для Java 8 или новее - использовать
Optional
класс.Это особенно удобно для длинных цепочек возможных нулевых значений. Пример:
Пример того, как бросить исключение на нуль:
Java 7 представила
Objects.requireNonNull
метод, который может быть полезен, когда что-то должно быть проверено на ненулевое значение. Пример:источник
Могу я ответить на это более широко!
Мы обычно сталкиваемся с этой проблемой, когда методы получают параметры так, как мы этого не ожидали (неправильный вызов метода - ошибка программиста). Например: вы ожидаете получить объект, вместо этого вы получите ноль. Вы ожидаете получить строку как минимум с одним символом, вместо этого вы получите пустую строку ...
Так что нет разницы между:
}
или
Они оба хотят убедиться, что мы получили действительные параметры, прежде чем мы будем выполнять какие-либо другие функции.
Как уже упоминалось в некоторых других ответах, чтобы избежать вышеуказанных проблем, вы можете следовать схеме проектирования по контракту . Пожалуйста, смотрите http://en.wikipedia.org/wiki/Design_by_contract .
Чтобы реализовать этот шаблон в java, вы можете использовать основные java-аннотации, такие как javax.annotation.NotNull, или использовать более сложные библиотеки, такие как Hibernate Validator .
Просто образец:
Теперь вы можете безопасно разрабатывать основную функцию вашего метода, не проверяя входные параметры, они защищают ваши методы от непредвиденных параметров.
Вы можете пойти дальше и убедиться, что в вашем приложении могут быть созданы только допустимые pojos. (образец с сайта валидатора гибернации)
источник
javax
это, по определению, не «ядро Java».Я очень игнорирую ответы, которые предлагают использовать нулевые объекты в любой ситуации. Этот шаблон может нарушить контракт и похоронить проблемы все глубже и глубже, вместо того, чтобы решать их, не говоря уже о том, что использование не по назначению создаст еще одну кучу шаблонного кода, который потребует будущего обслуживания.
В действительности, если что-то возвращенное из метода может быть нулевым, и вызывающий код должен принять решение по этому вопросу, должен быть более ранний вызов, который гарантирует состояние.
Также имейте в виду, что шаблон нулевого объекта может потребовать много памяти, если использовать его без осторожности. Для этого - экземпляр NullObject должен совместно использоваться владельцами, а не быть уникальным экземпляром для каждого из них.
Также я бы не рекомендовал использовать этот шаблон, когда тип должен представлять собой примитивное представление типа - как математические объекты, которые не являются скалярами: векторы, матрицы, комплексные числа и объекты POD (Plain Old Data), которые предназначены для хранения состояния. в форме встроенных типов Java. В последнем случае вы должны вызывать методы-получатели с произвольными результатами. Например, что должен возвращать метод NullPerson.getName ()?
Стоит рассмотреть такие случаи, чтобы избежать абсурдных результатов.
источник
Делая это в вашем собственном коде, вы можете избежать! = Пустых проверок.
В большинстве случаев нулевые проверки защищают циклы над коллекциями или массивами, поэтому просто инициализируйте их пустыми, вам не понадобятся никакие нулевые проверки.
В этом есть небольшие накладные расходы, но оно того стоит для более чистого кода и меньшего количества исключений NullPointerException.
источник
Это самая распространенная ошибка, произошедшая для большинства разработчиков.
У нас есть несколько способов справиться с этим.
Подход 1:
notNull (Объектный объект, Строковое сообщение)
Подход 2:
Подход 3:
Подход 4:
источник
источник
ObjectUtils.defaultIfNull()
. Есть еще один общий:,ObjectUtils.firstNonNull()
который можно использовать для реализации стратегииfirstNonNull(bestChoice, secondBest, thirdBest, fallBack);