IllegalArgumentException или NullPointerException для нулевого параметра? [закрыто]

У меня есть простой метод установки для свойства, и null не подходит для этого конкретного свойства. Я всегда разрывался в этой ситуации: должен ли я бросить IllegalArgumentException или NullPointerException ? От javadocs оба кажутся подходящими. Есть ли какой-то понятый стандарт? Или это всего лишь одна из тех вещей, которые вы должны делать, что хотите, и оба они действительно верны?

531
задан 05.05.2020, 12:00

15 ответов

Это походит IllegalArgumentException, требуется, если бы Вы не хотите null быть позволенным значением, и эти NullPointerException был бы брошен, если бы Вы пробовали к использование переменная, которая оказывается null.

290
ответ дан 05.05.2020, 12:00
  • 1
    I' m не взволнованный по поводу someone' s инвертирование алгоритма... более взволнованного об их перенамерении фактической реализации алгоритма (т.е. исходный код) в их собственный продукт. Полагение, что 20 KLOC являются несколькими month' s работа для разработки, был бы он брать более или менее, чем несколько месяцев к... – ChrisW 16.02.2009, 04:16
  • 2
    Следующие ответы на этот вопрос приводят убедительные аргументы, что NullPointerException является корректным исключением: stackoverflow.com/a/8160/372926 ; stackoverflow.com/a/8196334/372926 ; и stackoverflow.com/a/6358/372926 . – SamStephens 05.05.2020, 12:01

Стандарт должен бросить NullPointerException. Вообще безошибочный "Эффективный Java" обсуждает это кратко в Объекте 42 (первый выпуск), Объект 60 (второй выпуск), или Объект 72 (третий выпуск) "Способствует использованию стандартных исключений":

"Возможно, все ошибочные вызовы метода сводятся к недопустимому аргументу или недопустимому состоянию, но другие исключения стандартно используются для определенных видов недопустимых аргументов и состояний. Если вызывающая сторона передает пустой указатель в некотором параметре, для которого запрещаются нулевые значения, соглашение диктует, что NullPointerException брошены, а не IllegalArgumentException".

160
ответ дан 05.05.2020, 12:01
  • 1
    Я категорически не согласен. NullPointerExceptions должен только быть брошен, если JVM accidentially следует за нулевой ссылкой. Вот в чем разница, которое помогает Вам, когда призвано посмотреть на код в 3 утром. – Thorbjørn Ravn Andersen 05.05.2020, 12:02
  • 2
    Я don' t обязательно соглашаются со стандартом (я мог на самом деле пойти так или иначе по проблеме), но именно это стандартное использование всюду по JDK, следовательно Эффективный Java, излагающий доводы для него. Я думаю, что это - случай выбора, следовать ли стандарту или сделать вещь, которую Вы чувствуете, является правильным. Если у Вас нет очень серьезного основания (и это, конечно, может квалифицировать), it' s лучше всего для следования общепринятой практике. – GaryF 05.05.2020, 12:03
  • 3
    Трассировка исключения показывает точку исключения, поэтому если различие в типе исключения вызывает ад для Вас или является " различие, которое помогает you" Вы делаете что-то очень неправильно. – Jim Balter 05.05.2020, 12:04

Это - вопрос о стиле "священной войны". В словах других обе альтернативы хороши, но у людей будут свои предпочтения, которые они защитят к смерти.

20
ответ дан 05.05.2020, 12:03

Я хотел выбрать Нулевые аргументы от других недопустимых аргументов, таким образом, я получил исключение из IAE под названием NullArgumentException. Даже не будучи должен прочитать сообщение об исключении, я знаю, что нулевой аргумент был передан в метод и путем чтения сообщения, я узнаю, какой аргумент был пустым. Я все еще ловлю NullArgumentException с обработчиком IAE, но в моих журналах то, где я вижу различие быстро.

4
ответ дан 05.05.2020, 12:03
  • 1
    Я принял " бросьте новый IllegalArgumentException (" нечто == null") " подход. Необходимо зарегистрировать имя переменной так или иначе (чтобы быть уверенным, что Вы смотрите на правильный оператор и т.д.), – Thorbjørn Ravn Andersen 05.05.2020, 12:04

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

if( variable == null )
    throw new IllegalArgumentException("The object 'variable' cannot be null");

у Вас нет фактически причины неявно использовать "NullPointerException". NullPointerException является исключением, выданным виртуальной машиной Java, когда Вы пытаетесь выполнить код на нулевой ссылке (Как toString () ).

6
ответ дан 05.05.2020, 12:04

Если Вы принимаете решение бросить NPE, и Вы используете аргумент в своем методе, это могло бы быть избыточно и дорого явно проверить на пустой указатель. Я думаю, что VM уже делает это для Вас.

-5
ответ дан 05.05.2020, 12:05
  • 1
    @ChrisW, нисколько. Исходное Воровство! = Взламывание. Инвертирование приложения на грани способности взломать его состоит не в том где около того же самого как инвертирование значительного блока исходного кода от него. И путаница isn' t, что делает инвертирование любой большой части приложения трудным. – mmcdole 16.02.2009, 03:39
  • 2
    На самом деле этот комментарий мог получить некоторое другое мнение. Позвольте VM говорить в NPE все же, программисты говорят в IAE перед VM, если они хотят. – Jin Kwon 05.05.2020, 12:05
  • 3
    Дорогой? Я don' t думают, что == пустой указатель является настолько дорогим... Около, нулевой аргумент может быть просто сохранен для последнего использования и выдаст исключение после вызова метода, совершая ошибку тяжелее для отслеживания. Или можно создать дорогой объект перед использованием нулевого аргумента и так далее. Раннее обнаружение, кажется, хороший вариант. – PhiLho 05.05.2020, 12:06
  • 4
    Привычка времени выполнения включает значимое сообщение. – mP. 05.05.2020, 12:07

Если это - "метод set", или где-нибудь я заставляю участника использовать позже, я склонен использовать IllegalArgumentException.

, Если это - что-то, которое я собираюсь использовать (разыменовывают) прямо сейчас в методе, я бросаю NullPointerException заранее. Мне нравится это лучше, чем разрешение времени выполнения сделать это, потому что я могу обеспечить, полезное сообщение (кажется, что время выполнения могло сделать это также, но это - напыщенная речь в течение другого дня).

, Если я переопределяю метод, я использую то, что использует переопределенный метод.

-1
ответ дан 05.05.2020, 12:05
  • 1
    У меня обычно есть два DBS на приложение в моей локальной системе, один, чтобы разработать и выполнить локальный веб-сервер против, и другой для автоматизированных интеграционных тестов. – tvanfosson 03.10.2019, 12:39

Если бы это setter, метод и null передается ему, я думаю, что имело бы больше смысла бросать IllegalArgumentException. NullPointerException, кажется, имеет больше смысла в случае, где Вы пытаетесь на самом деле использовать null.

Так, при использовании его и это null, NullPointer. Если это передается в, и это null, IllegalArgument.

17
ответ дан 05.05.2020, 12:07

Не мог согласиться больше с тем, что говорится. Перестали работать рано, перестали работать быстро. Довольно хорошая молитва Исключения.

вопрос, о котором Исключением бросить является главным образом вопрос персонального вкуса. В моем уме IllegalArgumentException кажется более конкретным, чем использование NPE, так как это говорит мне, что проблема была с аргументом, который я передал методу а не со значением, которое, возможно, было сгенерировано при выполнении метода.

Мои 2 цента

7
ответ дан 05.05.2020, 12:08

В этом случае IllegalArgumentException передает ясную информацию пользователю, использующему Ваш API, который "не должен быть пустым". Поскольку другие пользователи форума указали, что Вы могли использовать NPE, если Вы хотите, пока Вы передаете правильную информацию пользователю, использующему Ваш API.

GaryF и tweakt отбросили "Эффективный Java" (которым я клянусь), ссылки, который рекомендует использовать NPE. И взгляд на то, как другие хорошие API создаются, является лучшим способом видеть, как создать Ваш API.

Другой хороший пример должен посмотреть на API Spring. Например, org.springframework.beans. BeanUtils.instantiateClass (Конструктор ctor, Объект [] args) имеет Assert.notNull (ctor, "Конструктор не должен быть пустым"), строка. org.springframework.util. Assert.notNull (Объектный объект, Строковое сообщение) проверки метода, чтобы видеть, передал ли аргумент (объект) в, являются пустыми и если это - он, бросает новый IllegalArgumentException (сообщение), которое тогда поймано в org.springframework.beans. BeanUtils.instantiateClass (...) метод.

-1
ответ дан 05.05.2020, 12:08
  • 1
    Я сказал что I' m пытающийся предотвратить: кража исходного кода конкурирующим поставщиком программного обеспечения, который мог бы тогда включить его в их собственный продукт. – ChrisW 16.02.2009, 02:41

Необходимо бросить IllegalArgumentException, поскольку он сделает его очевидным для программиста, что он сделал что-то недопустимое. Разработчики так привыкли к наблюдению NPE, брошенного VM, что любой программист сразу не осознал бы своей ошибки, и начнет озираться случайным образом, или хуже, обвинит Ваш код в том, что он был 'багги'.

-1
ответ дан 05.05.2020, 12:09
  • 1
    Мой ответ был предназначен, чтобы быть широким и покрыть путаницу как общий подход антивмешательства. – Kevin Loney 16.02.2009, 02:53
  • 2
    Извините, если программист осматривает " randomly" после получения любого вида исключения... меняющего имя исключения isn' t собирающийся помогать многому. – Christopher Smith 05.05.2020, 12:09

Определениями от ссылок до этих двух исключений выше является IllegalArgumentException: Брошенный, чтобы указать, что метод был передан недопустимый или несоответствующий аргумент. NullPointerException: Брошенный, когда приложение пытается использовать пустой указатель в случае, где объект требуется.

большой разницей здесь является IllegalArgumentException, как, предполагается, используется при проверке, что аргумент методу допустим. NullPointerException, как предполагается, используется каждый раз, когда объект, "используемый", когда это является пустым.

я надеюсь, что это помогает поместить два в перспективу.

-1
ответ дан 05.05.2020, 12:09
  • 1
    Если несколько разработчиков совместно используют ту же базу данных, конфликты данных могут произойти при выполнении версий разработки, может вмешаться другие разработчики. – linquize 03.10.2019, 12:39
  • 2
    Существенный бит - то, что это приложение , которое использует пустой указатель, не время выполнения. Таким образом, существует довольно большое перекрытие между " когда метод был передан недопустимый или несоответствующий argument" и " когда приложение использует null". в теории, если приложение передает пустой указатель для поля, которое требует непустого указателя, соответствуют обоим критериям. – Christopher Smith 05.05.2020, 12:10

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

5
ответ дан 05.05.2020, 12:11
  • 1
    JavaDoc на NPE имеет другое мнение: " Приложения должны бросить экземпляры этого класса для указания на другое недопустимое использование пустого объекта ". Don' t быть настолько категориальным – Donz 05.05.2020, 12:11

Я склонен следовать за дизайном библиотек JDK, особенно Наборы и Параллелизм (Joshua Bloch, Doug Lea, те парни знают, как разработать твердые API). Так или иначе, много API в JDK заранее бросает NullPointerException.

, Например, Javadoc для Map.containsKey состояния:

@throws NullPointerException, если ключ является пустым и эта карта, не разрешает пустые ключи (дополнительно).

Это совершенно допустимо для броска собственного NPE. Соглашение состоит в том, чтобы включать название параметра, которое было пустым в сообщении исключения.

шаблон идет:

public void someMethod(Object mustNotBeNull) {  
    if (mustNotBeNull == null) {  
        throw new NullPointerException("mustNotBeNull must not be null");  
    }  
}

Независимо от того, что Вы делаете, не позволяйте плохому значению быть установленным и выдавайте исключение позже, когда другой код пытается использовать его. Это делает отладку кошмара. Вы всегда должны следование за принципом "сбоя быстро".

69
ответ дан 05.05.2020, 12:12
  • 1
    @Gili: возможно, эта проблема существует во-первых, потому что Java не поддерживает множественное наследование. Если Java поддерживает MI, you' d быть в состоянии выдать исключение, которое наследовалось и IllegalArgumentException и NullPointerException. – Lie Ryan 05.05.2020, 12:13
  • 2
    Сообщение не должно включать аргумент, так как это было бы всегда пустым, дав: " пустой указатель не должен быть null" не очень полезный.:-) Иначе, я соглашаюсь, можно сделать " rich" NPE, со значимым сообщением. – PhiLho 05.05.2020, 12:14
  • 3
    Пища для размышления: Возможно, причина тот NullPointerException doesn' t расширяются, IllegalArgumentException - то, что первый может произойти в случаях, не включающих аргументы метода. – Gili 05.05.2020, 12:14

Необходимо использовать IllegalArgumentException (IAE), не NullPointerException (NPE) по следующим причинам:

Первый, NPE JavaDoc явно перечисляет случаи, где NPE является соответствующим. Заметьте, что все они брошены временем выполнения , когда null используется неуместно. Напротив, IAE JavaDoc не мог быть более ясным: "Брошенный, чтобы указать, что метод был передан недопустимый или несоответствующий аргумент". Да, это - Вы!

1110-секундный, когда Вы видите NPE в отслеживании стека, что Вы принимаете? Вероятно то, что кто-то разыменовал null. Когда Вы видите IAE, Вы предполагаете, что вызывающая сторона метода наверху стека передала в недопустимом значении. Снова, последнее предположение верно, первый вводит в заблуждение.

В-третьих, так как IAE ясно разработан для проверки параметров, необходимо ли принять его как выбор по умолчанию исключения, итак, почему Вы выбрали бы NPE вместо этого? Конечно, не для различного поведения - Вы действительно ожидаете, что код вызова поймает NPE's отдельно от IAE и сделает что-то другое в результате? Вы пытаетесь передать более определенное сообщение об ошибке? Но можно сделать это в тексте сообщения об исключении так или иначе, как Вы должны для всех других неправильных параметров.

Четвертый, все другие неправильные данные параметра будут IAE, итак, почему бы не последовательный? Почему случается так, что нелегал null является столь особенным, что это заслуживает отдельного исключения из всех других типов недопустимых аргументов?

Наконец, я принимаю аргумент, данный другими ответами, что части API Java используют NPE этим способом. Однако API Java несовместим со всем от типов исключительной ситуации до соглашений о присвоении имен, таким образом, я думаю, просто вслепую копируя (Ваша любимая часть), API Java не является достаточно хорошим аргументом для превосхождения этих других соображений.

410
ответ дан 05.05.2020, 12:13
  • 1
    К сожалению, методы проверки Validate.notNull (свободное городское население Ленг) и Preconditions.checkNotNull (гуава) оба броска NPE:-( – Aaron Digulla 05.05.2020, 12:13
  • 2
    Эффективный Java 2-й Выпуск, Объект 60: " Возможно, все ошибочные вызовы метода сводятся к недопустимому аргументу или недопустимому состоянию, но другие исключения стандартно используются для определенных видов недопустимых аргументов и состояний. Если вызывающая сторона передает пустой указатель в некотором параметре, для которого запрещаются нулевые значения, соглашение диктует, что NullPointerException брошены, а не IllegalArgumentException. Точно так же, если вызывающая сторона передает значение из диапазона в параметре, представляющем индекс в последовательность, IndexOutOfBoundsException должен быть брошен, а не IllegalArgumentException." – Gili 05.05.2020, 12:14
  • 3
    JavaDoc для NPE также заявляет следующее: " Приложения должны бросить экземпляры этого класса для указания на другое недопустимое использование пустого объекта " Этот мог быть более ясным: ( – R. Martinho Fernandes 05.05.2020, 12:14
  • 4
    Хотя Гуава также имеет Preconditions.checkArgument (), бросает IllegalArgumentException... – michaelok 05.05.2020, 12:14

Теги

Похожие вопросы