IllegalArgumentException ou NullPointerException para um parâmetro nulo?

votos
483

Eu tenho um método setter simples para uma propriedade e nullnão é apropriado para esta propriedade particular. Eu sempre fui rasgado nesta situação: eu deveria lançar uma IllegalArgumentException, ou um NullPointerException? Desde os javadocs, ambos parecem apropriadas. Existe algum tipo de padrão entendeu? Ou isso é apenas uma daquelas coisas que você deve fazer tudo o que você preferir e ambos são realmente correto?

Publicado 06/08/2008 em 20:26
fonte usuário
Em outras línguas...                            


26 respostas

votos
383

Você deve estar usando IllegalArgumentException(IAE), não NullPointerException(NPE), pelas seguintes razões:

Primeiro, o JavaDoc NPE lista explicitamente os casos em que NPE é apropriado. Note-se que todos eles são jogados pelo tempo de execução quando nullé usado de forma inadequada. Em contraste, o IAE JavaDoc não poderia ser mais claro: "Lançado para indicar que um método tem sido passado um argumento ilegal ou inapropriado." Sim, isso é você!

Em segundo lugar, quando você vê um NPE em um rastreamento de pilha, o que você supor? Provavelmente que alguém desreferenciado um null. Quando você vê IAE, você assume o chamador do método no topo da pilha aprovada em um valor ilegal. Novamente, a última hipótese for verdadeira, o primeiro é enganosa.

Em terceiro lugar, uma vez IAE é claramente desenhado para validar os parâmetros, você tem que assumir isto como a opção padrão de exceção, então por que você escolher NPE em vez disso? Certamente não para o comportamento diferente - Você realmente espera que o código de chamada para pegar do NPE separadamente do IAE e fazer algo diferente, como resultado? Você está tentando comunicar uma mensagem de erro mais específica? Mas você pode fazer isso no texto da mensagem de exceção de qualquer maneira, como você deve para todos os outros parâmetros incorretos.

Em quarto lugar, todos os outros dados de parâmetros incorrecta será IAE, então por que não ser consistente? Por que é que um ilegal nullé tão especial que merece uma exceção em separado de todos os outros tipos de argumentos ilegais?

Finalmente, eu aceito o argumento dado por outras respostas que partes do NPE utilização API Java desta maneira. No entanto, a API Java é inconsistente com tudo, desde os tipos de exceção para convenções de nomenclatura, então eu acho que apenas copiando cegamente (sua parte favorita) a API Java não é um bom argumento suficiente para trunfo estas outras considerações.

Respondeu 06/09/2008 em 19:29
fonte usuário

votos
263

Parece que um IllegalArgumentExceptioné chamado para se você não quer nullser um valor permitido, e NullPointerExceptionseria lançada se você estava tentando usar uma variável que acaba por ser null.

Respondeu 06/08/2008 em 20:29
fonte usuário

votos
144

O padrão é jogar a NullPointerException. A geralmente infalível "Effective Java" discute esta brevemente no Item 42 (primeira edição), ponto 60 (segunda edição), ou Item 72 (terceira edição) "favorecer a utilização de excepções padrão":

"Sem dúvida, todos os método invocações errôneas resumem-se a um argumento ilegal ou estado ilegal, mas outras exceções são vulgarmente utilizado para certos tipos de argumentos ilegais e estados. Se um chamador passa nula em algum parâmetro para o qual os valores nulos são proibidos, convenção dita que NullPointerException ser jogado em vez de IllegalArgumentException ".

Respondeu 11/08/2008 em 21:05
fonte usuário

votos
121

Eu estava tudo em favor de jogar IllegalArgumentExceptionpara parâmetros nulos, até hoje, quando notei o java.util.Objects.requireNonNullmétodo em Java 7. Com esse método, em vez de fazer:

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

você pode fazer:

Objects.requireNonNull(param);

e ele vai jogar um NullPointerExceptionse o parâmetro que você passa é null.

Dado que esse método é bang no meio de java.utileu tomar a sua existência ser uma indicação muito forte de que jogando NullPointerExceptioné "o caminho Java de fazer as coisas".

Eu acho que estou decidido, em qualquer taxa.

Note-se que os argumentos sobre a depuração difícil são falsos, porque você pode, naturalmente, proporcionar uma mensagem a NullPointerExceptiondizer que era nulo e por isso não deve ser nulo. Assim como com IllegalArgumentException.

Uma vantagem adicional de NullPointerExceptioné que, no altamente código crítico de desempenho, você pode dispensar uma verificação explícita para nulo (e um NullPointerExceptioncom uma mensagem de erro amigável), e apenas confiar no NullPointerExceptionque você vai receber automaticamente quando você chamar um método do nulo parâmetro. Desde que você chamar um método rápido (ou seja, falhar rápido), então você tem essencialmente o mesmo efeito, apenas não é tão amigável para o desenvolvedor. Na maioria das vezes, é provavelmente melhor para verificar explicitamente e jogar com uma mensagem útil para indicar qual parâmetro foi nula, mas é bom ter a opção de mudar isso se o desempenho dita sem quebrar o contrato publicada do método / construtor.

Respondeu 19/11/2011 em 19:42
fonte usuário

votos
63

I tendem a seguir o desenho de bibliotecas JDK, especialmente coleções e Concorrência (Joshua Bloch, Doug Lea, esses caras sabem como projetar APIs sólidos). De qualquer forma, muitas APIs do JDK joga pro-ativamente NullPointerException.

Por exemplo, o Javadoc para Map.containsKeyestados:

@throws NullPointerException se a chave é nula e este mapa não permite chaves null (opcional).

É perfeitamente válido para lançar seu próprio NPE. A convenção é incluir o nome do parâmetro que foi nula na mensagem de excepção.

O padrão vai:

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

Faça o que fizer, não deixe que um valor ruim para se definir e lançar uma exceção mais tarde, quando outro código tenta usá-lo. Isso faz com que a depuração de um pesadelo. Você deve sempre a seguir o princípio "fail-fast".

Respondeu 08/08/2008 em 21:35
fonte usuário

votos
38

Votado-se o argumento de Jason Cohen porque foi bem apresentado. Deixe-me desmembrá-la passo a passo. ;-)

  • O JavaDoc NPE diz explicitamente, "outros usos ilegais do objeto nulo" . Se ele foi apenas limitado a situações em que o tempo de execução encontra um nulo quando não deveria, todos esses casos poderia ser definido muito mais sucinta.

  • Não posso fazer nada se você assumir a coisa errada, mas encapsulamento assumindo é aplicado corretamente, você realmente não deve se preocupar ou perceber se um nulo foi desreferenciado inadequadamente vs. se um método detectou um nulo inadequada e disparou uma exceção off.

  • Eu escolheria NPE sobre IAE por várias razões

    • É mais específicas sobre a natureza da operação ilegal
    • A lógica que permite erroneamente nulos tende a ser muito diferente da lógica que permite erroneamente valores ilegais. Por exemplo, se eu estou validando dados inseridos por um usuário, se eu conseguir valor que é inaceitável, a fonte de que o erro é com o usuário final da aplicação. Se eu conseguir um nulo, que é erro do programador.
    • Valores inválidos podem causar coisas como estouros de pilha, erros de memória, exceções de análise, etc. Na verdade, a maioria dos erros geralmente apresentam, em algum momento, como um valor inválido de alguma chamada de método. Por esta razão eu vejo IAE como realmente o mais geral de todas as excepções previstas RuntimeException.
  • Na verdade, outros argumentos inválidos podem resultar em todos os tipos de outras exceções. UnknownHostException , FileNotFoundException , uma variedade de exceções erro de sintaxe, IndexOutOfBoundsException , falhas de autenticação, etc., etc.

Em geral, eu sinto NPE é muito criticado porque, tradicionalmente, tem sido associado com o código que não segue o princípio rápido falhar . Falha que, além do JDK para preencher NPE do com uma seqüência mensagem realmente criou um forte sentimento negativo que não é procedente. Na verdade, a diferença entre NPE e IAE partir de uma perspectiva de tempo de execução é estritamente o nome. A partir dessa perspectiva, o mais preciso você está com o nome, o mais clareza você dá para o chamador.

Respondeu 09/12/2009 em 07:07
fonte usuário

votos
19

É uma "Guerra Santa" questão de estilo. Em palavras outras, ambas as alternativas são boas, mas as pessoas terão suas preferências que eles vão defender até a morte.

Respondeu 17/10/2008 em 14:31
fonte usuário

votos
16

Se é um settermétodo e nullestá sendo passado para ele, eu acho que faria mais sentido para lançar uma IllegalArgumentException. Um NullPointerExceptionparece fazer mais sentido no caso em que você está tentando realmente usar o null.

Então, se você estiver usando-lo e é null, NullPointer. Se ele está sendo passado e é null, IllegalArgument.

Respondeu 06/08/2008 em 20:31
fonte usuário

votos
9

Apache Commons Lang tem um NullArgumentException que faz uma série de coisas discutidas aqui: ela se estende IllegalArgumentException e seu único construtor leva o nome do argumento que deveria ter sido não nulo.

Enquanto eu sentir que jogar algo como um NullArgumentException ou IllegalArgumentException descreve com mais precisão as circunstâncias excepcionais, meus colegas e eu optaram por diferir o conselho de Bloch sobre o assunto.

Respondeu 02/07/2009 em 05:47
fonte usuário

votos
7

Não poderia estar mais de acordo com o que está sendo dito. Falhar cedo, falhar rapidamente. Muito bom mantra Exceção.

A questão sobre a qual Exceção para jogar é principalmente uma questão de gosto pessoal. Em minha mente IllegalArgumentException parece mais específico do que usar um NPE, uma vez que está me dizendo que o problema era com um argumento I passado para o método e não com um valor que pode ter sido gerada durante a execução do método.

Meus 2 centavos

Respondeu 22/08/2008 em 12:11
fonte usuário

votos
6

Na verdade, a questão de jogar IllegalArgumentException ou NullPointerException é na minha humilde opinião apenas uma "guerra santa" para uma minoria com uma compreensão incomlete de tratamento de exceções em Java. Em geral, as regras são simples, e como se segue:

  • violações argumento de restrição deve ser indicado o mais rápido possível (-> rápido falhar), a fim de evitar estados ilegais que são muito mais difíceis de depurar
  • no caso de um ponteiro nulo inválida por qualquer motivo, lançar NullPointerException
  • no caso de um índice de matriz / recolha ilegal, jogar ArrayIndexOutOfBounds
  • no caso de um tamanho negativo matriz / recolha, jogar NegativeArraySizeException
  • no caso de um argumento ilegal que não é coberto pela acima, e para o qual você não tem outro tipo de exceção mais específico, jogue IllegalArgumentException como um cesto de lixo
  • Por outro lado, em caso de uma violação de restrição dentro de um campo que não poderia ser evitada por rápido falhar por alguma razão válida, captura e relançar como IllegalStateException ou uma exceção verificada mais específico. Nunca deixe passar a NullPointerException original, ArrayIndexOutOfBounds, etc neste caso!

Há pelo menos três razões muito boas contra o caso de mapear todos os tipos de violações argumento de restrição para IllegalArgumentException, com o terceiro provavelmente ser tão grave como para marcar a prática um estilo ruim:

(1) Um programador não pode assumir uma forma segura de que todos os casos de violações de restrição argumento resultar em IllegalArgumentException, porque a grande maioria das classes padrão usar esta exceção e como uma lixeira se não houver tipo mais específico de exceção disponível. Tentando mapear todos os casos de violações argumento constrangimento para IllegalArgumentException em sua API só leva ao programador frustração usando suas classes, como as bibliotecas padrão em sua maioria seguem regras diferentes que violam seu, e a maioria de seus usuários API irá utilizá-los também!

(2) Mapear as exceções realmente resulta em um tipo diferente de anomalia, causada por herança simples: Todas as exceções Java são classes, e, portanto, suportar apenas herança simples. Portanto, não há nenhuma maneira de criar uma exceção que é realmente dizer tanto um NullPointerException e um IllegalArgumentException, como subclasses só pode herdar de um ou outro. Lançar uma IllegalArgumentException no caso de um argumento nulo, portanto, torna mais difícil para os usuários da API para distinguir entre problemas sempre que um programa tenta corrigir programaticamente o problema, por exemplo, alimentando valores padrão em uma repetição chamada!

(3) Mapeamento realmente cria o perigo de mascaramento bug: Para mapear violações argumento de restrição em IllegalArgumentException, você vai precisar para codificar um try-catch exterior dentro de cada método que tem quaisquer argumentos restritos. No entanto, basta pegar RuntimeException neste bloco catch é fora de questão, pois que os riscos RuntimeExceptions mapeamento documentado lançadas por métodos libery utilizados dentro seu em IllegalArgumentException, mesmo que eles não são causados ​​por violações argumento de restrição. Então, você precisa ser muito específico, mas mesmo que o esforço não protegê-lo do caso que você acidentalmente mapear uma exceção tempo de execução sem documentos de outra API (ou seja, um bug) em um IllegalArgumentException de sua API.

Com a prática padrão, por outro lado, as regras permanecer simples, e as causas de exceção ficar desmascarado e específico. Para o chamador método, as regras são fáceis, bem como: - se você encontrar uma exceção de tempo de execução documentada de qualquer tipo, porque você passou um valor ilegal, quer repetir a chamada com um padrão (para este exceções específicas são neccessary), ou corrigir o seu código - Se, por outro lado, você enccounter uma exceção de tempo de execução que não está documentada a acontecer para um determinado conjunto de argumentos, um relatório de bug para os tomadores do método para garantir que tanto o seu código ou sua documentação é fixo.

Respondeu 31/12/2012 em 18:44
fonte usuário

votos
6

A prática aceite se usar o IllegalArgumentException (String message) para declarar um parâmetro a ser inválido e dar o máximo de detalhes possível ... Então quer dizer que um parâmetro foi encontrado para ser nula enquanto exceção não nulo, você faria algo como isso:

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

Você tem praticamente nenhuma razão para usar implicitamente a "NullPointerException". A NullPointerException é uma exceção lançada pela Máquina Virtual Java quando você tenta executar o código em referência nula (como toString () ).

Respondeu 11/08/2008 em 20:43
fonte usuário

votos
5

Lançar uma exceção que é exclusiva para nullos argumentos (se NullPointerExceptionou um tipo personalizado) faz automatizado nullde teste mais confiável. Esse teste automatizado pode ser feito com reflexão e um conjunto de valores predefinidos, como em goiaba 's NullPointerTester. Por exemplo, NullPointerTesterse tentar chamar o método a seguir ...

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

... com duas listas de argumentos: "", nulle null, ImmutableList.of(). Seria testar que cada uma dessas chamadas joga o esperado NullPointerException. Para esta implementação, passando por uma nulllista que não produzem NullPointerException. É, no entanto, acontecer para produzir um IllegalArgumentExceptionporque NullPointerTesterpassa a utilizar uma string padrão de "". Se NullPointerTesterespera apenas NullPointerExceptionpara nullvalores, ele pega o bug. Se ele espera IllegalArgumentException, ele perde-lo.

Respondeu 09/11/2012 em 17:30
fonte usuário

votos
4

NullPointerException acionada quando tentar acessar um objeto com uma variável de referência cujo valor atual é nulo

IllegalArgumentException lançada quando um método recebe um argumento formatado de forma diferente do que o método espera

Respondeu 23/06/2015 em 13:51
fonte usuário

votos
4

Algumas coleções assumir que nullé rejeitada utilizando NullPointerException, em vez de IllegalArgumentException. Por exemplo, se você comparar um conjunto contendo nulla um conjunto que rejeita null, o primeiro conjunto chamará containsAllpor outro e pegar a sua NullPointerException- mas não IllegalArgumentException. (Eu estou olhando para a implementação AbstractSet.equals.)

Você poderia razoavelmente argumentar que o uso de exceções não verificadas desta forma é uma antipattern, que as coleções comparando que contêm nulla coleções que não pode conter nullum bug provável que realmente deve produzir uma exceção, ou que colocar nullem uma coleção em tudo é uma má idéia . No entanto, a menos que você está disposto a dizer que equalsdeve lançar uma exceção em tal caso, você está se lembrando preso que NullPointerExceptioné necessária em determinadas circunstâncias, mas não em outros. ( "IAE antes NPE exceto após 'c' ...")

Respondeu 09/11/2012 em 17:18
fonte usuário

votos
4

a dicotomia ... Eles são não-sobreposição? Apenas partes não sobrepostas de um todo pode fazer uma dicotomia. Da maneira que eu vejo:

throw new IllegalArgumentException(new NullPointerException(NULL_ARGUMENT_IN_METHOD_BAD_BOY_BAD));
Respondeu 17/04/2012 em 18:15
fonte usuário

votos
4

Eu queria destacar argumentos nulos de outros argumentos ilegais, então eu derivada uma exceção de IAE chamado NullArgumentException. Sem necessidade de ler a mensagem de exceção, eu sei que um argumento nulo foi passado para um método e lendo a mensagem, eu descobrir qual argumento era nulo. Eu ainda pegar o NullArgumentException com um manipulador de IAE, mas em meus logs é onde eu posso ver a diferença rapidamente.

Respondeu 17/01/2009 em 01:13
fonte usuário

votos
3

Como uma questão subjetiva este deve ser fechado, mas como sua ainda em aberto:

Isso faz parte da política interna usada no meu lugar de actividade anterior e funcionou muito bem. Isto é tudo da memória para que eu não me lembro o texto exato. Vale a pena notar que eles não usar exceções verificadas, mas que está além do alcance da questão. As exceções não verificadas que fizeram uso caiu em 3 categorias principais.

NullPointerException: Não jogue intencionalmente. NPE são para ser jogado apenas pela VM quando dereferencing uma referência nula. Todos esforço possível deve ser feito para garantir que estes nunca são lançados. @Nullable e @NotNull deve ser usado em conjunto com ferramentas de análise de código para encontrar esses erros.

IllegalArgumentException:. Lançada quando um argumento para uma função não se conforma com a documentação pública, de tal forma que o erro pode ser identificada e descrita em termos dos argumentos passados ​​na situação do OP que se enquadram nessa categoria.

IllegalStateException: Lançada quando uma função é chamada e seus argumentos são ou inesperado no momento em que são passados ​​ou incompatível com o estado do objeto o método é um membro do grupo.

Por exemplo, havia duas versões internas do IndexOutOfBoundsException utilizados em coisas que tinham um comprimento. Uma sub-classe de IllegalStateException, usado se o índice era maior do que o comprimento. A outra subclasse de IllegalArgumentException, usado se o índice foi negativo. Isso foi porque você pode adicionar mais itens para o objeto eo argumento seria válido, enquanto um número negativo nunca é válido.

Como eu disse, este sistema funciona muito bem, e levou alguém para explicar por que a distinção está lá: "Dependendo do tipo de erro é bastante simples para que você possa descobrir o que fazer Mesmo que você não pode realmente. descobrir o que deu errado, você pode descobrir onde pegar esse erro e criar informações de depuração adicional."

NullPointerException: lidar com o caso nulo ou colocar em uma afirmação para que o NPE não é lançada. Se você colocar em uma afirmação que deve um dos outros dois tipos. Se possível, continuar a depuração, como se a afirmação estava lá em primeiro lugar.

IllegalArgumentException: você tem algo errado em seu callsite. Se os valores que está sendo passado em são de outra função, descobrir por que você está recebendo um valor incorreto. Se você está passando em um de seus argumentos propagar o erro verifica-se a pilha de chamadas até encontrar a função que não está retornando o que você espera.

IllegalStateException: Você não ligou suas funções na ordem correta. Se você estiver usando um de seus argumentos, vê-los e lançar uma IllegalArgumentException descrevendo o problema. Você pode, então, propagar as bochechas até a pilha até encontrar o problema.

De qualquer forma, seu ponto era que você só pode copiar os IllegalArgumentAssertions a pilha. Não há nenhuma maneira de você para propagar as IllegalStateExceptions ou NullPointerExceptions a pilha porque eles tinham algo a ver com a sua função.

Respondeu 23/09/2016 em 10:07
fonte usuário

votos
3

De acordo com seu cenário, IllegalArgumentExceptioné a melhor escolha, porque nullnão é um valor válido para a sua propriedade.

Respondeu 05/06/2015 em 09:43
fonte usuário

votos
3

Em geral, um desenvolvedor deve nunca mais lançar um NullPointerException. Essa exceção é lançada pelo tempo de execução quando o código tenta dereference uma variável que é valor é nulo. Portanto, se o seu método quer proibir explicitamente nulo, em oposição a apenas acontecer para ter um valor nulo levantar uma NullPointerException, você deve lançar uma IllegalArgumentException.

Respondeu 05/09/2008 em 11:34
fonte usuário

votos
0

Idealmente exceções de tempo de execução não devem ser jogados. A exceção verificada (exceção de negócios) deve ser criado para o seu cenário. Porque se qualquer um destes exceção é lançada e registrado, ele desvia o desenvolvedor ao atravessar os logs. Em vez disso exceções de negócios não criar esse pânico e geralmente ignorados enquanto solução de problemas logs.

Respondeu 18/08/2016 em 08:40
fonte usuário

votos
-1

Neste caso, IllegalArgumentException transmite informações claras para o usuário através do seu API que o "não deve ser nulo". Como outros usuários do fórum apontou você poderia usar a NPE se você quiser, contanto que você transmitir a informação certa para o usuário usar a sua API.

GaryF e tweakt caiu "Effective Java" (que eu juro por) referências que recomenda o uso de NPE. E olhando como outras boas APIs são construídas é a melhor maneira de ver como construir a sua API.

Outro bom exemplo é olhar para as APIs da Primavera. Por exemplo, org.springframework.beans.BeanUtils.instantiateClass (Construtor ctor, Object [] args) tem um Assert.notNull (ctor "Construtor não deve ser nulo") linha. org.springframework.util.Assert.notNull (object Object, mensagem String) método verifica para ver se o argumento (objeto) passado é nulo e se for ele lança um novo IllegalArgumentException (mensagem) que é então pego no org. springframework.beans.BeanUtils.instantiateClass (...) método.

Respondeu 29/10/2008 em 17:20
fonte usuário

votos
-1

Você deve lançar uma IllegalArgumentException, uma vez que irá torná-lo óbvio para o programador que ele tenha feito algo inválido. Os desenvolvedores estão tão acostumados a ver NPE lançada pelo VM, que qualquer programador não iria perceber imediatamente seu erro, e iria começar a olhar ao redor aleatoriamente, ou pior, culpa seu código para ser 'Buggy'.

Respondeu 09/09/2008 em 05:13
fonte usuário

votos
-1

Se é um "setter", ou em algum lugar eu estou ficando um membro para usar mais tarde, eu tendem a usar IllegalArgumentException.

Se é algo que eu vou usar (dereference) agora no método, eu jogo uma NullPointerException de forma proativa. Eu gosto deste melhor do que deixar o tempo de execução fazê-lo, porque eu posso fornecer uma mensagem útil (parece que o tempo de execução poderia fazer isso também, mas isso é um discurso retórico para outro dia).

Se eu estou substituindo um método, eu uso qualquer que seja o método substituído usa.

Respondeu 28/08/2008 em 19:03
fonte usuário

votos
-1

As definições dos links para as duas exceções acima são IllegalArgumentException: Lançado para indicar que um método tem sido passado um argumento ilegal ou impróprio. NullPointerException: lançada quando uma aplicação tenta usar nula em um caso onde um objecto é requerido.

A grande diferença aqui é o IllegalArgumentException é suposto ser usado quando a verificação de que um argumento para um método é válido. NullPointerException é suposto ser usado sempre que um objeto que está sendo "usado" quando é nulo.

Espero que ajuda a colocar os dois em perspectiva.

Respondeu 16/08/2008 em 19:13
fonte usuário

votos
-5

Se você optar por jogar uma NPE e você estiver usando o argumento em seu método, pode ser redundante e caro para verificar explicitamente para um nulo. Eu acho que a VM já faz isso para você.

Respondeu 11/08/2008 em 14:20
fonte usuário

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