Question IllegalArgumentException ou NullPointerException pour un paramètre null? [fermé]


J'ai une méthode simple de réglage pour une propriété et null n'est pas approprié pour cette propriété particulière. J'ai toujours été déchiré dans cette situation: devrais-je jeter un IllegalArgumentExceptionou un NullPointerException? À partir des javadocs, les deux semblent appropriés. Y a-t-il une sorte de norme comprise? Ou est-ce juste une de ces choses que vous devriez faire ce que vous préférez et les deux sont vraiment corrects?


488
2017-08-06 19:26


origine


Réponses:


Cela ressemble à un IllegalArgumentException est appelé si vous ne voulez pas null être une valeur autorisée, et le NullPointerException serait jeté si vous essayiez de utilisation une variable qui s'avère être null.


267
2017-08-06 19:29



Vous devriez utiliser IllegalArgumentException (IAE), pas NullPointerException (NPE) pour les raisons suivantes:

Premièrement la NPE JavaDoc répertorie explicitement les cas où NPE est approprié. Notez que tous sont jetés par le runtime quand null est utilisé de manière inappropriée. En revanche, le IAE JavaDoc ne pouvait pas être plus clair: "Jeté pour indiquer qu'une méthode a été adoptée un argument illégal ou inapproprié." Ouais, c'est toi!

Deuxièmement, quand vous voyez un NPE dans une trace de pile, que supposez-vous? Probablement que quelqu'un a déréférencé un null. Lorsque vous voyez IAE, vous supposez que l'appelant de la méthode en haut de la pile est passé dans une valeur illégale. Encore une fois, cette dernière hypothèse est vraie, la première est trompeuse.

Troisièmement, étant donné que IAE est clairement conçu pour la validation des paramètres, vous devez l'assumer comme choix d'exception par défaut, alors pourquoi choisiriez-vous NPE à la place? Certainement pas pour un comportement différent - vous attendez-vous vraiment à ce que le code d'appel attrape les NPE séparément de l'IAE et fasse quelque chose de différent en conséquence? Essayez-vous de communiquer un message d'erreur plus spécifique? Mais vous pouvez le faire dans le texte du message d'exception de toute façon, comme vous le feriez pour tous les autres paramètres incorrects.

Quatrièmement, toutes les autres données de paramètres incorrectes seront IAE, alors pourquoi ne pas être cohérent? Pourquoi est-ce que c'est illégal null est si spécial qu'il mérite une exception distincte de tous les autres types d'arguments illégaux?

Enfin, j'accepte l'argument donné par d'autres réponses que certaines parties de l'API Java utilisent NPE de cette manière. Cependant, l'API Java est incompatible avec tout, des types d'exception aux conventions de dénomination, donc je pense que la copie aveugle (votre partie préférée) de l'API Java n'est pas un argument suffisant pour l'emporter sur ces autres considérations.


386
2017-09-06 18:29



La norme est de lancer l'exception NullPointerException. Le "Java efficace", généralement infaillible, en parle brièvement dans l'article 42 (première édition), article 60 (deuxième édition), ou article 72 (troisième édition) "Favoriser l'utilisation d'exceptions types":

"Sans doute, toute méthode erronée   les invocations se résument à un illégale   argument ou état illégal, mais d'autres   exceptions sont généralement utilisés pour   certains types d'arguments illégaux et   États. Si un appelant passe null   un paramètre pour lequel des valeurs nulles   sont interdites, convention dicte   que NullPointerException soit levé   plutôt que IllegalArgumentException. "


146
2017-08-11 20:05



J'étais en faveur du lancer IllegalArgumentException pour les paramètres nuls, jusqu'à aujourd'hui, quand j'ai remarqué la java.util.Objects.requireNonNull méthode en Java 7. Avec cette méthode, au lieu de faire:

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

tu peux faire:

Objects.requireNonNull(param);

et il jettera un NullPointerException si le paramètre que vous transmettez est null.

Étant donné que cette méthode est juste en plein milieu de java.util Je prends son existence pour être une indication assez forte que jeter NullPointerException est "la façon de faire de Java".

Je pense que je suis décidé en tout cas.

Notez que les arguments sur le débogage dur sont faux parce que vous pouvez bien sûr fournir un message à NullPointerException dire ce qui était nul et pourquoi il ne devrait pas être nul. Comme avec IllegalArgumentException.

Un avantage supplémentaire de NullPointerException est que, dans un code critique très performant, vous pourriez vous passer d’une vérification explicite de null (et NullPointerException avec un message d'erreur amical), et juste compter sur le NullPointerException vous obtiendrez automatiquement lorsque vous appelez une méthode sur le paramètre null. Pourvu que vous appeliez une méthode rapidement (c'est-à-dire en cas d'échec rapide), alors vous avez essentiellement le même effet, mais pas tout à fait aussi facile à utiliser pour le développeur. La plupart du temps, il est probablement préférable de vérifier explicitement et de lancer avec un message utile pour indiquer quel paramètre est nul, mais il est intéressant d'avoir la possibilité de le changer si la performance le dicte sans rompre le contrat publié de la méthode / constructeur.


122
2017-11-19 18:42



J'ai tendance à suivre la conception des bibliothèques JDK, en particulier Collections et Concurrency (Joshua Bloch, Doug Lea, ces gars-là savent comment concevoir des API solides). Quoi qu'il en soit, de nombreuses API dans le JDK jette pro-activement NullPointerException.

Par exemple, le Javadoc pour Map.containsKey États:

@throws NullPointerException si la clé est null et cette carte     n'autorise pas les clés NULL (facultatif).

C'est parfaitement valable pour lancer votre propre NPE. La convention est d'inclure le nom du paramètre qui était nul dans le message de l'exception.

Le modèle va:

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

Quoi que vous fassiez, n'autorisez pas qu'une mauvaise valeur soit définie et lancez une exception ultérieurement lorsque d'autres codes tentent de l'utiliser. Cela rend le débogage un cauchemar. Vous devez toujours suivre le principe "échec rapide".


64
2017-08-08 20:35



Jugé l'argument de Jason Cohen parce que c'était bien présenté. Laissez-moi le démembrer pas à pas. ;-)

  • le NPE JavaDoc dit explicitement, "autres utilisations illégales de l'objet null". Si cela se limitait à des situations où le runtime rencontre une valeur nulle alors qu'il ne le devrait pas, tous ces cas pourraient être définis de manière beaucoup plus succincte.

  • Ne peut pas aider si vous supposez la mauvaise chose, mais en supposant que l'encapsulation est appliquée correctement, vous ne devriez vraiment pas se soucier ou remarquer si un null a été déréférencé de manière inappropriée ou si une méthode a détecté un null inapproprié et déclenché une exception.

  • Je choisirais NPE plus de IAE pour plusieurs raisons

    • Il est plus précis sur la nature de l'opération illégale
    • La logique qui autorise par erreur les valeurs nulles tend à être très différente de la logique qui autorise par erreur des valeurs illégales. Par exemple, si je valide des données saisies par un utilisateur, si je reçois une valeur qui est inacceptable, la source de cette erreur est avec l'utilisateur final de l'application. Si j'obtiens une valeur nulle, c'est une erreur de programmeur.
    • Les valeurs non valides peuvent entraîner des débordements de pile, des erreurs de mémoire insuffisante, des exceptions d'analyse, etc. En effet, la plupart des erreurs présentent généralement, à un moment donné, une valeur non valide dans un appel de méthode. Pour cette raison, je vois IAE comme le fait LA PLUS GÉNÉRALE de toutes les exceptions sous RuntimeException.
  • En fait, d'autres arguments non valides peuvent entraîner toutes sortes d'autres exceptions. UnknownHostException, FileNotFoundException, une variété d'exceptions d'erreur de syntaxe, IndexOutOfBoundsException, échecs d'authentification, etc., etc.

En général, j’estime que NPE est beaucoup décrié parce qu’il a traditionnellement été associé à du code qui ne échouer le principe rapide. Cela, plus l'échec du JDK à remplir les NPE avec une chaîne de message a vraiment créé un fort sentiment négatif qui n'est pas bien fondé. En effet, la différence entre NPE et IAE d'un point de vue de l'exécution est strictement le nom. De ce point de vue, plus vous êtes précis avec le nom, plus vous donnez de la clarté à l'appelant.


39
2017-12-09 06:07



C'est une question de style "guerre sainte". En d'autres termes, les deux alternatives sont bonnes, mais les gens auront leurs préférences qu'ils défendront jusqu'à la mort.


19
2017-10-17 13:31



Si c'est un setter méthode et null est passé à lui, je pense qu'il serait plus logique de jeter un IllegalArgumentException. UNE NullPointerException semble avoir plus de sens dans le cas où vous essayez d'utiliser réellement le null.

Donc, si vous l'utilisez et c'est null, NullPointer. Si c'est transmis et c'est null, IllegalArgument.


16
2017-08-06 19:31



Apache Commons Lang a un NullArgumentException cela fait un certain nombre de choses discutées ici: il étend IllegalArgumentException et son seul constructeur prend le nom de l'argument qui aurait dû être non nul.

Bien que j'estime que lancer quelque chose comme une exception NullArgumentException ou IllegalArgumentException décrit plus précisément les circonstances exceptionnelles, mes collègues et moi-même avons choisi de nous en remettre aux conseils de Bloch sur le sujet.


9
2017-07-02 04:47