java - IllegalArgumentException ou NullPointerException pour un paramètre null?

Translate

J'ai une méthode de setter simple pour une propriété etnulln'est pas approprié pour cette propriété particulière. J'ai toujours été déchiré dans cette situation: devrais-je lancer unIllegalArgumentException, ou unNullPointerException? D'après les javadocs, les deux semblent appropriés. Existe-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 que les deux sont vraiment correctes?

This question and all comments follow the "Attribution Required."

Toutes les réponses

Translate

Cela ressemble à unIllegalArgumentExceptionest appelé si vous ne voulez pasnullêtre une valeur autorisée, et leNullPointerExceptionserait jeté si vous essayiez deutilisationune variable qui s'avère êtrenull.

La source
Translate

Vous devriez utiliserIllegalArgumentException(IAE), pasNullPointerException(NPE) pour les raisons suivantes:

Premièrement leNPE JavaDocénumère explicitement les cas où NPE est approprié. Notez que tous sont jetéspar le runtimequandnullest utilisé de manière inappropriée. En revanche, leIAE JavaDocne pourrait pas être plus clair: "Lancé pour indiquer qu'une méthode a reçu un argument illégal ou inapproprié." Ouais, c'est toi!

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

Troisièmement, puisque IAE est clairement conçu pour valider les paramètres, vous devez le considérer comme le 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 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 quand même le faire dans le texte du message d'exception, comme vous devriez le faire 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 qu'un illégalnullest 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 selon lequel certaines parties de l'API Java utilisent NPE de cette manière. Cependant, l'API Java est incompatible avec tout, des types d'exceptions aux conventions de dénomination, donc je pense que le simple fait de copier aveuglément (votre partie préférée de) l'API Java n'est pas un argument suffisant pour éclipser ces autres considérations.

La source
Translate

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

"On peut soutenir que toutes les invocations de méthode erronées se résument à un argument ou à un état illégal, mais d’autres exceptions sont généralement utilisées pour certains types d’arguments et d’états illégaux. Si un appelant transmet null dans un paramètre pour lequel les valeurs nulles sont interdites, la convention stipule que NullPointerException être levée plutôt que IllegalArgumentException. "

La source
MB.
Translate

J'étais tout à fait en faveur de jeterIllegalArgumentExceptionpour les paramètres nuls, jusqu'à aujourd'hui, quand j'ai remarqué lejava.util.Objects.requireNonNullmé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 ça jettera unNullPointerExceptionsi le paramètre que vous passez estnull.

Étant donné que cette méthode est en plein milieu dejava.utilJe prends son existence comme une indication assez forte que jeterNullPointerExceptionest "la manière Java de faire les choses".

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

Notez que les arguments sur le débogage dur sont faux car vous pouvez bien sûr fournir un message àNullPointerExceptiondire ce qui était nul et pourquoi il ne devrait pas être nul. Tout comme avecIllegalArgumentException.

Un avantage supplémentaire deNullPointerExceptionest que, dans un code hautement performant, vous pouvez vous dispenser d'une vérification explicite de null (etNullPointerExceptionavec un message d'erreur convivial), et comptez simplement sur leNullPointerExceptionvous obtiendrez automatiquement lorsque vous appelez une méthode sur le paramètre null. Si vous appelez une méthode rapidement (c'est-à-dire échouez rapidement), alors vous avez essentiellement le même effet, mais pas tout à fait aussi convivial pour le développeur. La plupart du temps, il est probablement préférable de vérifier explicitement et de lancer un message utile pour indiquer quel paramètre était nul, mais c'est bien d'avoir la possibilité de le modifier si les performances le dictent sans rompre le contrat publié de la méthode / du constructeur.

La source
Translate

J'ai tendance à suivre la conception des bibliothèques JDK, en particulier les collections et la concurrence (Joshua Bloch, Doug Lea, ces gars-là savent comment concevoir des API solides). Quoi qu'il en soit, de nombreuses API du JDK lancent de manière proactiveNullPointerException.

Par exemple, le Javadoc pourMap.containsKeyÉtats:

@throws NullPointerException si la clé est nulle et que cette mappe n'autorise pas les clés nulles (facultatif).

Il est parfaitement valable de lancer votre propre NPE. La convention consiste à 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, ne permettez pas à une valeur incorrecte d'être définie et de lever une exception plus tard lorsque d'autres codes tentent de l'utiliser. Cela fait du débogage un cauchemar. Vous devez toujours suivre le principe du "fail-fast".

La source
Translate

A voté l'argument de Jason Cohen parce qu'il était bien présenté. Permettez-moi de le démembrer étape par étape. ;-)

  • leNPE JavaDocdit explicitement,"autres utilisations illégales de l'objet nul". S'il était juste limité aux situations où le runtime rencontre un null alors qu'il ne le devrait pas, tous ces cas pourraient être définis beaucoup plus succinctement.

  • Vous ne pouvez pas vous en empêcher si vous supposez la mauvaise chose, mais en supposant que l'encapsulation est appliquée correctement, vous ne devriez vraiment pas vous soucier ou remarquer si un null a été déréférencé de manière inappropriée par rapport au fait qu'une méthode ait détecté un null inapproprié et déclenché une exception.

  • Je choisiraisNPEplus deIAEpour 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 a tendance à ê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 j'obtiens une valeur 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 invalides peuvent provoquer des débordements de pile, des erreurs de mémoire insuffisante, des exceptions d'analyse, etc. Pour cette raison, je vois IAE comme en fait leLE PLUS GÉNÉRALde 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, je pense que NPE est très décrié car il est traditionnellement associé à un code qui ne suit pas leprincipe de l'échec rapide. Cela, ajouté à 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 du 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 clarté à l'appelant.

La source
Translate

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.

La source
Translate

Si c'est unsetterméthode etnulllui est transmis, je pense qu'il serait plus logique de lancer unIllegalArgumentException. UNENullPointerExceptionsemble avoir plus de sens dans le cas où vous essayez d'utiliser réellement lenull.

Donc, si vous l'utilisez et que c'estnull, NullPointer. Si c'est passé et c'estnull, IllegalArgument.

La source
Translate

Apache Commons Lang a unNullArgumentExceptionqui fait un certain nombre des 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 je pense que lancer quelque chose comme NullArgumentException ou IllegalArgumentException décrit plus précisément les circonstances exceptionnelles, mes collègues et moi avons choisi de nous en remettre aux conseils de Bloch sur le sujet.

La source
Translate

Je ne pourrais pas être plus d'accord avec ce qui est dit. Échouez tôt, échouez vite. Très bon mantra d'exception.

La question de savoir quelle exception lancer est principalement une question de goût personnel. Dans mon esprit, IllegalArgumentException semble plus spécifique que l'utilisation d'un NPE car il me dit que le problème était avec un argument que j'ai passé à la méthode et non avec une valeur qui peut avoir été générée lors de l'exécution de la méthode.

Mes 2 cents

La source
Translate

En fait, la question de lancer IllegalArgumentException ou NullPointerException n'est à mon humble avis qu'une "guerre sainte" pour une minorité ayant une compréhension incomparable de la gestion des exceptions en Java. En général, les règles sont simples et comme suit:

  • les violations de contrainte d'argument doivent être signalées le plus rapidement possible (-> fast fail), afin d'éviter les états illégaux qui sont beaucoup plus difficiles à déboguer
  • en cas de pointeur nul non valide pour une raison quelconque, lancez NullPointerException
  • dans le cas d'un index de tableau / collection non autorisé, lancez ArrayIndexOutOfBounds
  • dans le cas d'une taille de tableau / collection négative, lancez NegativeArraySizeException
  • en cas d'argument illégal qui n'est pas couvert par ce qui précède, et pour lequel vous n'avez pas d'autre type d'exception plus spécifique, lancez IllegalArgumentException comme corbeille à papier
  • d'autre part, en cas de violation de contrainte DANS UN CHAMP qui ne pourrait pas être évitée par un échec rapide pour une raison valable, attrapez et relancez comme IllegalStateException ou une exception vérifiée plus spécifique. Ne laissez jamais passer le NullPointerException d'origine, ArrayIndexOutOfBounds, etc. dans ce cas!

Il y a au moins trois très bonnes raisons contre le cas du mappage de toutes sortes de violations de contrainte d'argument à IllegalArgumentException, la troisième étant probablement si grave qu'elle marque le mauvais style de pratique:

(1) Un programmeur ne peut pas supposer en toute sécurité que tous les cas de violations de contraintes d'argument aboutissent à IllegalArgumentException, car la grande majorité des classes standard utilisent cette exception plutôt comme une corbeille à papier s'il n'y a pas de type d'exception plus spécifique disponible. Essayer de mapper tous les cas de violations de contraintes d'argument à IllegalArgumentException dans votre API ne conduit qu'à la frustration du programmeur en utilisant vos classes, car les bibliothèques standard suivent principalement des règles différentes qui violent les vôtres, et la plupart de vos utilisateurs d'API les utiliseront également!

(2) Le mappage des exceptions aboutit en fait à un type d'anomalie différent, causé par un héritage unique: toutes les exceptions Java sont des classes et ne prennent donc en charge que l'héritage unique. Par conséquent, il n'existe aucun moyen de créer une exception qui est vraiment à la fois une NullPointerException et une IllegalArgumentException, car les sous-classes ne peuvent hériter que de l'un ou de l'autre. Lancer une IllegalArgumentException en cas d'argument nul rend donc plus difficile pour les utilisateurs d'API de faire la distinction entre les problèmes chaque fois qu'un programme tente de corriger le problème par programme, par exemple en introduisant des valeurs par défaut dans une répétition d'appel!

(3) Le mappage crée en fait le danger de masquage de bogue: afin de mapper les violations de contrainte d'argument dans IllegalArgumentException, vous devrez coder un try-catch externe dans chaque méthode qui a des arguments contraints. Cependant, il est hors de question de simplement intercepter RuntimeException dans ce bloc catch, car cela risque de mapper les RuntimeExceptions documentées lancées par les méthodes de librairie utilisées dans la vôtre dans IllegalArgumentException, même si elles ne sont pas causées par des violations de contrainte d'argument. Vous devez donc être très spécifique, mais même cet effort ne vous protège pas du cas où vous mappez accidentellement une exception d'exécution non documentée d'une autre API (c'est-à-dire un bogue) dans une exception IllegalArgumentException de votre API. Même le mappage le plus soigné risque donc de masquer les erreurs de programmation d'autres fabricants de bibliothèques comme des violations de contrainte d'argument des utilisateurs de votre méthode, ce qui est tout simplement un comportement accidentel!

Avec la pratique standard en revanche, les règles restent simples et les causes d'exception restent démasquées et spécifiques. Pour l'appelant de méthode, les règles sont également simples: - si vous rencontrez une exception d'exécution documentée de quelque nature que ce soit parce que vous avez passé une valeur illégale, répétez l'appel avec une valeur par défaut (pour cela, des exceptions spécifiques sont nécessaires), ou corrigez votre code - si d'un autre côté vous rencontrez une exception d'exécution qui n'est pas documentée pour se produire pour un ensemble d'arguments donné, déposez un rapport de bogue aux créateurs de la méthode pour vous assurer que leur code ou leur documentation est corrigé.

La source
Translate

La pratique acceptée consiste à utiliser leIllegalArgumentException (message de chaîne)pour déclarer un paramètre invalide et donner autant de détails que possible ... Donc, pour dire qu'un paramètre a été trouvé nul alors que l'exception n'est pas nulle, vous feriez quelque chose comme ceci:

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

Vous n'avez pratiquement aucune raison d'utiliser implicitement "NullPointerException". La NullPointerException est une exception levée par la machine virtuelle Java lorsque vous essayez d'exécuter du code sur une référence nulle (commetoString ()).

La source
Translate

Lancer une exception exclusive ànullarguments (siNullPointerExceptionou un type personnalisé) rend automatisénulltest plus fiable. Ce test automatisé peut être effectué avec une réflexion et un ensemble de valeurs par défaut, comme dansGoyavedeNullPointerTester. Par exemple,NullPointerTestertenterait d'appeler la méthode suivante ...

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

... avec deux listes d'arguments:"", nulletnull, ImmutableList.of(). Cela permettrait de tester que chacun de ces appels jette leNullPointerException. Pour cette implémentation, passer unnullliste faitne pasproduireNullPointerException. Il arrive cependant de produire unIllegalArgumentExceptioncarNullPointerTesterutilise une chaîne par défaut de"". SiNullPointerTesterattend seulementNullPointerExceptionpournullvaleurs, il attrape le bogue. S'il attendIllegalArgumentException, ça lui manque.

La source
Translate

En général, un développeur doitjamaislancer une NullPointerException. Cette exception est levée par le runtime lorsque le code tente de déréférencer une variable dont la valeur est null. Par conséquent, si votre méthode souhaite explicitement interdire null, au lieu de simplement avoir une valeur null lever une NullPointerException, vous devez lever une IllegalArgumentException.

La source
Translate

Certaines collections supposent quenullest rejeté en utilisantNullPointerExceptionplutôt queIllegalArgumentException. Par exemple, si vous comparez un ensemble contenantnullà un ensemble qui rejettenull, le premier poste appelleracontainsAllde l'autre et attraper sonNullPointerException-- mais nonIllegalArgumentException. (Je regarde la mise en œuvre deAbstractSet.equals.)

Vous pouvez raisonnablement affirmer que l'utilisation d'exceptions non vérifiées de cette manière est un anti-modèle, que comparer des collections qui contiennentnullaux collections qui ne peuvent pas contenirnullest un bug probable quidevraitproduire une exception, ou que mettrenulldans une collection du tout est une mauvaise idée. Néanmoins, à moins que vous ne vouliez dire çaequalsdevrait lever une exception dans un tel cas, vous êtes coincé en vous rappelant queNullPointerExceptionest nécessaire dans certaines circonstances mais pas dans d'autres. ("IAE avant NPE sauf après 'c' ...")

La source
Fanny Lee
Translate

En tant que question subjective, cela devrait être fermé, mais comme il est toujours ouvert:

Cela fait partie de la politique interne utilisée à mon ancien lieu de travail et cela a très bien fonctionné. Tout cela vient de mémoire, donc je ne me souviens pas du libellé exact. Il convient de noter qu'ils n'ont pas utilisé d'exceptions vérifiées, mais cela dépasse le cadre de la question. Les exceptions non contrôlées qu'ils ont utilisées se répartissaient en 3 catégories principales.

NullPointerException: ne pas lancer intentionnellement. Les NPE doivent être lancés uniquement par la machine virtuelle lors du déréférencement d'une référence nulle. Tous les efforts possibles doivent être faits pour que ceux-ci ne soient jamais lancés. @Nullable et @NotNull doivent être utilisés conjointement avec des outils d'analyse de code pour trouver ces erreurs.

IllegalArgumentException: levée lorsqu'un argument d'une fonction n'est pas conforme à la documentation publique, de sorte que l'erreur puisse être identifiée et décrite en termes d'arguments passés. La situation de l'OP tomberait dans cette catégorie.

IllegalStateException: levée lorsqu'une fonction est appelée et que ses arguments sont soit inattendus au moment où ils sont passés, soit incompatibles avec l'état de l'objet dont la méthode est membre.

Par exemple, il y avait deux versions internes de l'exception IndexOutOfBoundsException utilisées dans les choses qui avaient une longueur. Une sous-classe d'IllegalStateException, utilisée si l'index était plus grand que la longueur. L'autre est une sous-classe d'IllegalArgumentException, utilisée si l'index était négatif. Cela était dû au fait que vous pouviez ajouter plus d'éléments à l'objet et que l'argument serait valide, alors qu'un nombre négatif n'est jamais valide.

Comme je l'ai dit, ce système fonctionne très bien, et il a fallu quelqu'un pour expliquer pourquoi la distinction est là: "En fonction du type d'erreur, il est assez simple pour vous de savoir quoi faire. Même si vous ne pouvez pas vraiment comprendre ce qui n'a pas fonctionné, vous pouvez déterminer où intercepter cette erreur et créer des informations de débogage supplémentaires. "

NullPointerException: gérez la casse Null ou insérez une assertion afin que le NPE ne soit pas levé. Si vous mettez une assertion, c'est juste l'un des deux autres types. Si possible, continuez le débogage comme si l'assertion était là en premier lieu.

IllegalArgumentException: vous avez un problème sur votre site d'appel. Si les valeurs transmises proviennent d'une autre fonction, découvrez pourquoi vous recevez une valeur incorrecte. Si vous passez l'un de vos arguments, propagez l'erreur vérifie la pile d'appels jusqu'à ce que vous trouviez la fonction qui ne renvoie pas ce que vous attendez.

IllegalStateException: vous n'avez pas appelé vos fonctions dans le bon ordre. Si vous utilisez l'un de vos arguments, vérifiez-les et lancez une exception IllegalArgumentException décrivant le problème. Vous pouvez ensuite propager les joues contre la pile jusqu'à ce que vous trouviez le problème.

Quoi qu'il en soit, son point était que vous ne pouvez copier que les IllegalArgumentAssertions dans la pile. Il n'y a aucun moyen pour vous de propager les IllegalStateExceptions ou NullPointerExceptions vers le haut de la pile car ils ont quelque chose à voir avec votre fonction.

La source
Translate

Je voulais distinguer les arguments Null d'autres arguments illégaux, j'ai donc dérivé une exception de IAE nommée NullArgumentException. Sans même avoir besoin de lire le message d'exception, je sais qu'un argument nul a été passé dans une méthode et en lisant le message, je découvre quel argument était nul. J'attrape toujours l'exception NullArgumentException avec un gestionnaire IAE, mais c'est dans mes journaux que je peux voir la différence rapidement.

La source
Translate

la dichotomie ... Ne se chevauchent-elles pas? Seules les parties d'un tout qui ne se chevauchent pas peuvent faire une dichotomie. Comme je le vois:

throw new IllegalArgumentException(new NullPointerException(NULL_ARGUMENT_IN_METHOD_BAD_BOY_BAD));
La source
Translate

NullPointerException levée lors d'une tentative d'accès à un objet avec une variable de référence dont la valeur actuelle est null

IllegalArgumentException levée lorsqu'une méthode reçoit un argument mis en forme différemment de ce que la méthode attend

La source
leo
Translate

Selon votre scénario,IllegalArgumentExceptionest le meilleur choix, carnulln'est pas une valeur valide pour votre propriété.

La source
Translate

Idéalement, les exceptions d'exécution ne doivent pas être levées. Une exception cochée (exception métier) doit être créée pour votre scénario. Parce que si l'une de ces exceptions est levée et journalisée, cela égare le développeur en parcourant les journaux. Au lieu de cela, les exceptions commerciales ne créent pas cette panique et sont généralement ignorées lors du dépannage des journaux.

La source
Translate

Les définitions des liens vers les deux exceptions ci-dessus sont IllegalArgumentException: levée pour indiquer qu'une méthode a reçu un argument illégal ou inapproprié. NullPointerException: levée lorsqu'une application tente d'utiliser null dans un cas où un objet est requis.

La grande différence ici est que l'exception IllegalArgumentException est censée être utilisée pour vérifier qu'un argument d'une méthode est valide. NullPointerException est censé être utilisé chaque fois qu'un objet est "utilisé" lorsqu'il est nul.

J'espère que cela permet de mettre les deux en perspective.

La source
Translate

Si c'est un "setter", ou quelque part où je vais utiliser un membre plus tard, j'ai tendance à utiliser IllegalArgumentException.

Si c'est quelque chose que je vais utiliser (déréférencer) maintenant dans la méthode, je lance une NullPointerException de manière proactive. J'aime mieux cela que de laisser le runtime le faire, car je peux fournir un message utile (il semble que le runtime puisse le faire aussi, mais c'est une diatribe pour un autre jour).

Si je remplace une méthode, j'utilise tout ce que la méthode remplacée utilise.

La source
Translate

Vous devriez lancer une IllegalArgumentException, car cela rendra évident au programmeur qu'il a fait quelque chose d'invalide. Les développeurs sont tellement habitués à voir NPE jeté par la VM, que tout programmeur ne se rendrait pas compte immédiatement de son erreur et commencerait à chercher au hasard, ou pire, blâmerait votre code pour être «bogué».

La source
Oscar Lee
Translate

Dans ce cas, IllegalArgumentException transmet des informations claires à l'utilisateur à l'aide de votre API indiquant que "ne doit pas être nul". Comme d'autres utilisateurs du forum l'ont souligné, vous pouvez utiliser NPE si vous le souhaitez, à condition de transmettre les bonnes informations à l'utilisateur à l'aide de votre API.

GaryF et tweakt ont abandonné les références "Effective Java" (sur lesquelles je jure) qui recommande l'utilisation de NPE. Et regarder comment d'autres bonnes API sont construites est le meilleur moyen de voir comment construire votre API.

Un autre bon exemple est de regarder les API Spring. Par exemple, org.springframework.beans.BeanUtils.instantiateClass (Constructor ctor, Object [] args) a une ligne Assert.notNull (ctor, "Le constructeur ne doit pas être nul"). La méthode org.springframework.util.Assert.notNull (Object object, String message) vérifie si l'argument (objet) passé est nul et si c'est le cas, il lance une nouvelle IllegalArgumentException (message) qui est ensuite interceptée dans l'organisation. springframework.beans.BeanUtils.instantiateClass (...) méthode.

La source
Translate

Si vous choisissez de lancer un NPE et que vous utilisez l'argument dans votre méthode, il peut être redondant et coûteux de rechercher explicitement un null. Je pense que la VM le fait déjà pour vous.

La source