IllegalArgumentException или NullPointerException для нулевого параметра?

голоса
483

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

Задан 06/08/2008 в 20:26
источник пользователем
На других языках...                            


26 ответов

голоса
383

Вы должны использовать IllegalArgumentException(ИАЭ), а не NullPointerException(NPE) по следующим причинам:

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

Во- вторых, когда вы видите NPE в трассировки стека, что же вы предполагаете? Возможно , что кто - то разыменовываются null. Когда вы видите ИАЭ, вы предполагаете , вызывающий метод в верхней части стеки передается в недопустимом значении. Опять же , последнее предположение верно, бывший вводит в заблуждение.

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

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

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

Ответил 06/09/2008 d 19:29
источник пользователем

голоса
263

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

Ответил 06/08/2008 d 20:29
источник пользователем

голоса
144

Стандарт бросить NullPointerException. В целом непогрешимым «Эффективное Java» обсуждает этот кратко в пункте 42 (первая редакция), пункт 60 (второе издание), или пункт 72 (третье издание) «Фавор использование стандартных исключений»:

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

Ответил 11/08/2008 d 21:05
источник пользователем

голоса
121

Я был все в пользу метания IllegalArgumentExceptionнулевых параметров, до сегодняшнего дня, когда я заметил , что java.util.Objects.requireNonNullметод в Java 7. С этим методом, а не делать:

if (param == null) {
    throw new IllegalArgumentException("param cannot be null.");
}

ты можешь сделать:

Objects.requireNonNull(param);

и он будет бросать , NullPointerExceptionесли параметр вы передаете это null.

Учитывая , что этот метод подходит челка , в середине java.utilя беру свое существование , чтобы быть довольно сильным свидетельством того, что бросание NullPointerExceptionявляется «Java способ делать вещи».

Я думаю, что я решил в любом случае.

Обратите внимание , что аргументы о жестких отладках являются поддельными , потому что вы можете, конечно , предоставить сообщение NullPointerExceptionговоря , что было нулевым , и почему он не должен быть пустым. Так же , как с IllegalArgumentException.

Одно дополнительное преимущество в NullPointerExceptionтом , что в высокоразвитых производительности критического кода, можно обойтись без явных проверок на нуль (и NullPointerExceptionс сообщением об ошибке дружественного), и полагаться только на NullPointerExceptionвы получите автоматически при вызове методы на нуле параметр. При условии , вы вызываете метод быстро (т.е. не в состоянии быстро), то есть по существу тот же эффект, только не совсем , как пользователь дружественного для разработчика. В большинстве случаев это, вероятно , лучше , чтобы проверить явно и бросать с полезным сообщением , чтобы указать , какой параметр был нулевым, но это хорошо , чтобы иметь возможность изменить , что если производительность диктует , не нарушая опубликованный договор метода / конструктора.

Ответил 19/11/2011 d 19:42
источник пользователем

голоса
63

Я склонен следовать дизайн библиотек JDK, особенно коллекций и параллельности (Джошуа Блох, Дуг Леа, эти ребята знают , как проектировать твердые интерфейсы). Во всяком случае, многие интерфейсы 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");  
    }  
}

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

Ответил 08/08/2008 d 21:35
источник пользователем

голоса
38

Проголосовали вверх аргумент Джейсона Коэна, потому что он был хорошо представлен. Позвольте мне расчленить ее шаг за шагом. ;-)

  • JavaDoc NPE прямо говорит, «другое незаконное использование нулевого объекта» . Если он ограничивается только ситуациями , когда среда выполнения сталкивается нуль , когда он не должен, все такие случаи могут быть определены гораздо более сжато.

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

  • Я бы выбрал NPE над МИА по нескольким причинам

    • Более конкретно о характере незаконной операции
    • Логика, которая ошибочно позволяет аннулирует, как правило, сильно отличается от логики, которая ошибочно позволяет недопустимые значения. Например, если я проверки данных, вводимых пользователем, если я получаю значение, является неприемлемым, источником этой ошибки с конечным пользователем приложения. Если я получаю нуль, это ошибка программиста.
    • Неверные значения могут вызвать такие вещи , как переполнение стека, из - за ошибок памяти, синтаксического анализа исключений и т.д. На самом деле, большинство ошибок обычно присутствуют, в какой - то момент, как недопустимое значение в какой - то вызов метода. По этой причине я вижу IAE , как на самом деле в самом общем обо всех исключениях под RuntimeException.
  • На самом деле, другие недопустимые аргументы могут привести к всякого рода других исключений. UnknownHostException , FileNotFoundException , различные исключения ошибок синтаксиса, IndexOutOfBoundsException , неудачи аутентификации и т.д., и т.д.

В общем, я чувствую себя гораздо NPE клеветы , поскольку традиционно ассоциируется с кодом , который не следовать за неудачу быстрого принципа . Отказ это, плюс JDK для заполнения НЭП со строкой сообщения действительно создали сильное отрицательное чувство , которое не обоснованным. Действительно, разница между NPE и ИАЭ с точки зрения выполнения строго имя. С этой точки зрения, тем более точно вы с именем, тем больше ясности вы даете вызывающему абоненту.

Ответил 09/12/2009 d 07:07
источник пользователем

голоса
19

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

Ответил 17/10/2008 d 14:31
источник пользователем

голоса
16

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

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

Ответил 06/08/2008 d 20:31
источник пользователем

голоса
9

Apache Commons Lang есть NullArgumentException , что делает ряд вещей , обсуждаемых здесь: она простирается IllegalArgumentException и его единственный конструктор принимает имя аргумента , который должен был быть не равен нулю.

В то время как я чувствую, что бросать что-то вроде NullArgumentException или IllegalArgumentException более точно описывает исключительные обстоятельства, я и мои коллеги решили отложить советы Блохи по этому вопросу.

Ответил 02/07/2009 d 05:47
источник пользователем

голоса
7

Не могу согласиться с тем, что было сказано. Сбой в начале, не в состоянии быстро. Довольно хорошо Exception мантра.

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

Мои 2 Cents

Ответил 22/08/2008 d 12:11
источник пользователем

голоса
6

На самом деле, вопрос о метании IllegalArgumentException или NullPointerException в моей скромной точки зрения только «священной войны» для меньшинства с incomlete пониманием обработки исключений в Java. В общем, правила просты, и следующим образом:

  • нарушения аргумент ограничений должны быть указаны как можно быстрее (-> быстрый провал), для того, чтобы избежать незаконных государств, которые гораздо труднее отлаживать
  • в случае недопустимого указателя нулевого по какой-либо причине, бросить NullPointerException
  • в случае незаконного индекса массива / коллекции, бросать ArrayIndexOutOfBounds
  • в случае отрицательного размера массива / коллекции, бросать NegativeArraySizeException
  • в случае незаконного аргумента, который не охватывается выше, и для которых у вас нет другого более конкретного типа исключения, бросить IllegalArgumentException в мусорной корзине
  • с другой стороны, в случае нарушения ограничений в пределах поля, которые не могли быть избежать, быстро терпят неудачу по какой-то уважительной причине, улова и Rethrow как IllegalStateException или более конкретного проверяемого исключения. Никогда не пропустят оригинальный NullPointerException, ArrayIndexOutOfBounds и т.д. в этом случае!

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

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

(2) Отображение исключений фактически приводит к различного рода аномалии, вызванные одинарным наследованием: Все исключения Java классы, и, следовательно, поддерживает только единичное наследование. Таким образом, нет никакого способа, чтобы создать исключение, действительно сказать, как в NullPointerException и IllegalArgumentException, поскольку подклассы могут наследовать только от одного или другого. Бросив IllegalArgumentException в случае нулевого аргумента, следовательно, делает его более трудным для пользователей API различать проблемы, когда программа пытается программно исправить эту проблему, например, путем подачи значений по умолчанию в повторе вызова!

(3) Отображение на самом деле создает опасность ошибок маскирования: Чтобы отобразить нарушения аргумента ограничений Into IllegalArgumentException, вам нужно закодировать внешний примерочный улов в пределах каждого метода, который имеет какие-либо стесненные аргументы. Однако, просто ловить RuntimeException в этом блоке улова не может быть и речи, потому что риски отображения документально RuntimeExceptions брошенные методами Libery, используемых в твоих в IllegalArgumentException, даже если они не вызваны нарушениями аргумент ограничений. Таким образом, вы должны быть очень конкретными, но даже это усилие не защитит вас от случая, что вы случайно карты недокументированной исключение во время выполнения другого API (т.е. ошибки) в IllegalArgumentException вашего API.

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

Ответил 31/12/2012 d 18:44
источник пользователем

голоса
6

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

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

Вы практически не имеют никаких оснований косвенно использовать «NullPointerException». NullPointerException исключение брошено в виртуальной машине Java при попытке выполнить код на нулевой ссылке (как ToString () ).

Ответил 11/08/2008 d 20:43
источник пользователем

голоса
5

Бросив исключение, эксклюзив для nullаргументов (независимо от того NullPointerExceptionили пользовательского типа) делаешь автоматизированное nullтестирование более надежным. Это автоматизированное тестирование может быть сделано с отражением и набором значений по умолчанию, как в гуавы «s NullPointerTester. Например, NullPointerTesterбудет пытаться вызвать следующий метод ...

Foo(String string, List<?> list) {
  checkArgument(string.length() > 0);
  // missing null check for list!
  this.string = string;
  this.list = list;
}

... с двумя списками аргументов: "", nullи null, ImmutableList.of(). Было бы проверить , что каждый из этих вызовов бросков ожидаемые NullPointerException. Для реализации этого, передавая nullсписок никак не производят NullPointerException. Это, однако, случается производить IllegalArgumentExceptionпотому , что NullPointerTesterпроисходит , чтобы использовать строку по умолчанию "". Если NullPointerTesterожидает только NullPointerExceptionдля nullзначений, он ловит ошибку. Если он ожидает IllegalArgumentException, он пропускает его.

Ответил 09/11/2012 d 17:30
источник пользователем

голоса
4

NullPointerException выброшен при попытке получить доступ к объекту с опорной переменной, текущее значение равно нулю

IllegalArgumentException выбрасывается, если метод получает аргумент отформатированный иначе, чем метод ожидает

Ответил 23/06/2015 d 13:51
источник пользователем

голоса
4

Некоторые коллекции предполагают , что nullотвергается с использованием NullPointerExceptionвместо IllegalArgumentException. Например, если сравнить набор , содержащий nullв набор, отвергающего null, первый набор позвонит containsAllна другой и поймать ИТС NullPointerException- но не IllegalArgumentException. (Я смотрю на реализацию AbstractSet.equals) .

Можно обоснованно утверждать , что использование непроверенных исключения в этом случае является антипаттерн, что сравнивающие коллекции , которые содержат nullв коллекции , которые не могут содержать nullэто , вероятно , ошибка , которая действительно должна производить исключение, или положить nullв коллекцию на все это плохая идея , Тем не менее, если вы не готовы сказать , что equalsдолжен бросить исключение в таком случае, вы застряли Вспомнив , что NullPointerExceptionтребуется в определенных обстоятельствах , но не в других. ( "IAE перед тем NPE исключения после того, как 'с' ...")

Ответил 09/11/2012 d 17:18
источник пользователем

голоса
4

дихотомия ... Они не пересекаются? Только непересекающиеся части целого могут сделать дихотомии. Как я вижу это:

throw new IllegalArgumentException(new NullPointerException(NULL_ARGUMENT_IN_METHOD_BAD_BOY_BAD));
Ответил 17/04/2012 d 18:15
источник пользователем

голоса
4

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

Ответил 17/01/2009 d 01:13
источник пользователем

голоса
3

В качестве субъективного вопрос этот должен быть закрыт, но его все еще открыт:

Это является частью внутренней политики, используемой в моем предыдущем месте работы, и она работала очень хорошо. Это все из памяти, так что я не могу вспомнить точную формулировку. Ее стоит отметить, что они не использовали проверенные исключения, но это выходит за рамки вопроса. Непроверенное исключение они сделали использование упало на 3 основные категории.

NullPointerException: Не бросайте намеренно. NPEs должны быть брошены только VM, когда разыменования ссылки нулевой. Все возможные усилия должны быть сделаны, чтобы гарантировать, что они никогда не бросали. @Nullable и @NotNull следует использовать в сочетании с инструментами анализа кода, чтобы найти эти ошибки.

IllegalArgumentException:. Брошенный, когда аргумент функции не соответствует официальной документации, так что ошибки могут быть идентифицированы и описаны в терминах аргументов, передаваемых в ситуации Ор был бы попасть в эту категорию.

IllegalStateException: Метательное, когда функция вызывается и его аргументы являются либо неожиданным в то время они передаются или несовместим с состоянием объекта методом является членом.

Так, например, были две внутренние версии IndexOutOfBoundsException, используемые в вещах, которые имели длину. Один из суб-класс IllegalStateException, используется, если индекс был больше, чем длина. Другой подкласс IllegalArgumentException, используется, если индекс был отрицательным. Это потому, что вы могли бы добавить больше деталей к объекту и аргумент будет действительным, в то время как отрицательное число никогда не бывает.

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

NullPointerException: Ручка Null случай или положить в утверждении, так что NPE не выброшен. Если положить в утверждении, что должно один из двух других типов. Если это возможно, продолжить отладку, как если утверждение было в первую очередь.

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

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

Во всяком случае, его было то, что вы можете только скопировать IllegalArgumentAssertions стек. Там нет никакого способа для вас, чтобы размножить IllegalStateExceptions или NullPointerExceptions вверх по стеку, потому что они что-то делать с вашей функцией.

Ответил 23/09/2016 d 10:07
источник пользователем

голоса
3

По вашему сценарию, IllegalArgumentExceptionэто лучший выбор, потому что nullэто не является допустимым значением для вашего имущества.

Ответил 05/06/2015 d 09:43
источник пользователем

голоса
3

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

Ответил 05/09/2008 d 11:34
источник пользователем

голоса
0

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

Ответил 18/08/2016 d 08:40
источник пользователем

голоса
-1

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

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

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

Ответил 29/10/2008 d 17:20
источник пользователем

голоса
-1

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

Ответил 09/09/2008 d 05:13
источник пользователем

голоса
-1

Если это «сеттер», или где-то я получаю член, чтобы использовать позже, я предпочитаю использовать IllegalArgumentException.

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

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

Ответил 28/08/2008 d 19:03
источник пользователем

голоса
-1

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

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

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

Ответил 16/08/2008 d 19:13
источник пользователем

голоса
-5

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

Ответил 11/08/2008 d 14:20
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more