Question

J'ai une simple méthode de définition d'une propriété et null n'est pas approprié pour cette propriété particulière.J'ai toujours été déchiré dans cette situation:dois-je lancer une IllegalArgumentException, ou un NullPointerException?À partir de la documentation javadoc, les deux semblent appropriées.Est-il une sorte de une compris la norme?Ou est-ce juste une de ces choses que vous devez faire ce que vous préférez et les deux sont vraiment correcte?

Était-ce utile?

La solution

Il semble comme une IllegalArgumentException est appelé pour la si vous ne voulez pas null un permis de valeur, et les NullPointerException pourrait être levée si vous étiez à la utilisation une variable qui s'avère être null.

Autres conseils

Vous devriez être en utilisant IllegalArgumentException (IAE), pas NullPointerException (NPE) pour les raisons suivantes:

Tout d'abord, l' NPE JavaDoc explicitement énumère les cas où les NPE est approprié.Notez que tous d'entre eux sont jetés par le moteur d'exécution lorsque null est utilisé de façon inappropriée.En revanche, l' IAE JavaDoc ne pouvait pas être plus clair:"Levée pour indiquer qu'une méthode a été adoptée illégale ou inappropriée de l'argument." Yup, c'est vous!

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

En troisième lieu, l'IAE est clairement conçu pour la validation des paramètres, vous devez l'assumer, comme le choix par défaut de l'exception, alors pourquoi voudriez-vous choisir des NPE à la place?Certainement pas pour les différents comportement -- attendez-vous d'appeler le code d'attraper des NPE est séparément de l'IAE et de faire quelque chose de différent, comme un résultat?Êtes-vous essayer de communiquer un message d'erreur plus spécifique?Mais vous pouvez le faire à l'exception de message texte de toute façon, comme vous devriez le faire pour tous les autres des paramètres incorrects.

Quatrièmement, tous les autres paramètres incorrect de données sera de l'IAE, alors pourquoi ne pas cohérent?Pourquoi est-ce qu'un illégales null est tellement spécial qu'il mérite une autre exception de tous les autres types d'illégal arguments?

Enfin, j'accepte l'argument donné par d'autres réponses que des parties de l'API Java utilisation des NPE dans cette manière.Toutefois, l'API Java est incompatible avec tout, des types exception des conventions de nommage, donc je pense tout simplement copier aveuglément (votre partie préférée de l') de l'API Java n'est pas un assez bon argument pour l'emporter sur ces autres considérations.

La norme est de jeter le NullPointerException.Généralement infaillible "Effective Java" explique 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 de la norme exceptions":

"Sans doute, toutes erronées méthode les invocations se résument à un illégales argument ou d'état illégales, mais d'autres les exceptions sont normalement utilisés pour certains types d'arguments et illégale états.Si un appelant passe null dans un certain nombre de paramètres dont les valeurs null sont interdits, convention dicte que NullPointerException être jeté plutôt que de IllegalArgumentException."

J'étais tout à fait favorable à jeter 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.");
}

vous pouvez le faire:

Objects.requireNonNull(param);

et il va jeter un NullPointerException si le paramètre que vous col, il est null.

Étant donné que cette méthode est bang au milieu de java.util Je prends son existence à être assez forte indication que de jeter NullPointerException est "la Java façon de faire les choses".

Je pense que je suis décidé à n'importe quel taux.

Notez que les arguments sur dur de débogage sont fausses, parce que bien sûr, vous pouvez fournir un message à NullPointerException en disant ce qui était nulle et pourquoi il ne devrait pas être null.Tout comme avec IllegalArgumentException.

Un avantage supplémentaire de NullPointerException c'est que, dans très critique pour les performances de code, vous pouvez renoncer à une vérification explicite pour les nuls (et un NullPointerException avec un sympathique message d'erreur), et s'appuient sur les NullPointerException vous obtiendrez automatiquement lorsque vous appelez une méthode sur le paramètre null.À condition que vous appelez une méthode rapidement (c'est à direéchouer rapidement), alors vous avez essentiellement le même effet, pas tout à fait aussi facile pour le développeur.La plupart du temps, il est probablement préférable de vérifier explicitement et de le jeter avec un message utile pour indiquer le paramètre est null, mais c'est agréable d'avoir la possibilité de changer que si les performances dicte sans casser la publication contrat de la méthode ou le constructeur.

J'ai tendance à suivre la conception de JDK bibliothèques, en particulier des Collections et de la concurrence (Joshua Bloch, Doug Lea, ces gars-là savent comment la conception solide Api).De toute façon, de nombreuses Api du JDK pro-activement jette NullPointerException.

Par exemple, la Javadoc de Map.containsKey membres:

@throws exception NullPointerException si la clé est nulle et cette carte ne permet pas les clés null (optionnel).

Il est parfaitement valide de lancer votre propre NPE.La convention est d'inclure le nom du paramètre qui est nulle 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 laissez pas une mauvaise valeur pour obtenir définir et lancer une exception plus tard, quand d'autres le code tente de l'utiliser.Qui rend le débogage d'un cauchemar.Vous devriez toujours suivre le "fail-fast" principe.

Voté jusqu'Jason Cohen argument, car c'était bien présenté.Permettez-moi de le démembrer, étape par étape.;-)

  • L' NPE JavaDoc dit explicitement, "d'autres l'usage illicite de l'objet nul".Si c'était seulement limité aux situations où l'exécution de la rencontre avec une valeur null lorsqu'il ne devrait pas, tous ces cas pourraient être définis à présent de façon plus succincte.

  • Ne peux pas l'aider si vous assumez la mauvaise chose, mais en supposant que l'encapsulation est appliqué correctement, vous ne devriez vraiment pas de soins ou de l'avis de savoir si une valeur null est déréférencé de façon inappropriée vssi une méthode a détecté une inappropriée null et a tiré une exception off.

  • J'ai choisi NPE plus IAE pour de multiples raisons

    • Il est plus précis sur la nature de l'opération illégale
    • Une logique qui, à tort, nulls a tendance à être très différente de la logique qui, à tort, permet à des valeurs illégales.Par exemple, si je suis la validation des données saisies par un utilisateur, si j'obtiens la valeur qui est inacceptable, la source de cette erreur est du à l'utilisateur final de l'application.Si je reçois une valeur nulle, que le programmeur de l'erreur.
    • Des valeurs non valides peuvent causer des choses comme les débordements de pile, des erreurs de mémoire insuffisante, l'analyse des exceptions, etc.En effet, la plupart des erreurs présent de manière générale, à un certain point, comme une valeur non valide dans certains appel de méthode.Pour cette raison, je vois de l'IAE en réalité LA PLUPART DES GÉNÉRAUX de toutes les exceptions prévues dans les RuntimeException.
  • En fait, d'autres arguments non valides peuvent entraîner dans toutes sortes d'autres exceptions. UnknownHostException, FileNotFoundException, une variété d'erreur de syntaxe exceptions, IndexOutOfBoundsException, les échecs d'authentification, etc., etc.

En général, je me sens NPE est décrié parce que, traditionnellement, a été associée avec le code qui ne parvient pas à suivre le l'échec rapide de principe.Ça, plus le JDK de l'échec à remplir NPE avec une chaîne de message n'a vraiment créé un fort sentiment négatif qui n'est pas bien fondée.En effet, la différence entre les entrées en phase nationale et de l'IAE à partir d'un point de vue d'exécution est strictement le nom.De ce point de vue, le plus vous êtes précis, le nom, le plus de clarté vous donner à l'appelant.

C'est une "Guerre Sainte" question style.En d'autres termes, les deux solutions sont bonnes, mais les gens ont leurs préférences dont ils défendrai jusqu'à la mort.

Si c'est un setter méthode et null est passé pour elle, je pense qu'il serait plus judicieux de jeter un IllegalArgumentException.Un NullPointerException semble faire plus de sens dans le cas où vous êtes en essayant d'utiliser effectivement le null.

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

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

Alors que j'ai l'impression que de jeter quelque chose comme un NullArgumentException ou IllegalArgumentException décrit plus précisément les circonstances exceptionnelles, mes collègues et moi avons choisi de reporter à Bloch de conseils sur le sujet.

Ne pouvais pas être plus d'accord avec ce qui est dit.L'échec précoce, échec rapide.Assez bonne Exception mantra.

La question de l'Exception pour lancer est surtout une question de goût personnel.Dans mon esprit IllegalArgumentException semble plus précis que d'utiliser un NPE car il me dit que le problème était avec un argument que j'ai transmis à la méthode et non pas avec une valeur qui peut avoir été généré lors de l'exécution de la méthode.

Mes 2 Cents

La pratique acceptée si l'utilisation de la IllegalArgumentException( String message ) pour déclarer un paramètre invalide et donner autant de détails que possible...Donc, dire que un des paramètres a été trouvé nulle, alors que l'exception de non-nulle, il vous faudrait faire quelque chose comme ceci:

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

Vous n'avez pratiquement aucune raison de s'utilisent implicitement le "NullPointerException".Le NullPointerException est une exception levée par la Machine Virtuelle Java lorsque vous essayez d'exécuter du code sur la référence null (Comme toString()).

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

  • l'argument des violations de contrainte doit être indiqué aussi vite que possible (-> rapide échec), afin d'éviter illégale états qui sont beaucoup plus difficiles à déboguer
  • dans le cas d'une défaillance de pointeur null pour quelque raison que ce soit, de jeter des NullPointerException
  • dans le cas d'illégale d'un tableau ou d'une collection d'index, jeter erreur arrayindexoutofbounds
  • en cas de résultat négatif de tableau/taille de la collection, jetez NegativeArraySizeException
  • dans le cas d'un argument illégal qui n'est pas couvert par la ci-dessus, et pour lequel vous n'avez pas d'autre plus spécifique type d'exception, jeter IllegalArgumentException comme d'une poubelle
  • d'autre part, dans le cas d'une violation de contrainte à l'INTÉRIEUR d'UN CHAMP qui n'a pas pu être évitée par rapide échoue pour une raison valable, les attraper et de les renvoyer comme IllegalStateException ou plus spécifiques, vérifié exception.Ne jamais laisser passer l'original NullPointerException, erreur arrayindexoutofbounds, etc dans ce cas!

Il y a au moins trois bonnes raisons contre le cas de la cartographie de tous les genres de l'argumentation, les violations de contrainte à IllegalArgumentException, avec la troisième sans doute d'être si sévère pour marquer la pratique de mauvais style:

(1) Un programmeur ne peuvent pas présumer que tous les cas de l'argument de violation de contrainte de résultat dans IllegalArgumentException, parce que la grande majorité des classes standard cette exception plutôt comme d'une poubelle si il n'y a pas plus précis sorte d'exception disponibles.En essayant de carte tous les cas de l'argument des violations de contrainte à IllegalArgumentException dans votre API ne conduit qu'à la programmeur de la frustration à l'aide de vos classes, comme les bibliothèques standard pour la plupart suivent des règles différentes qui violent la vôtre, et la plupart de vos les utilisateurs de l'API s'en bien!

(2) Cartographie des exceptions en fait des résultats dans un autre type d'anomalie, causée par l'héritage simple:Tous Java les exceptions sont des classes, et donc de soutenir l'héritage unique seulement.Par conséquent, il n'y a aucun moyen de créer une exception qui est vraiment à dire à la fois une NullPointerException et une IllegalArgumentException, comme les sous-classes ne peuvent hériter de l'une ou de l'autre.Lancer une IllegalArgumentException dans le cas d'un argument null, par conséquent, rend plus difficile pour les utilisateurs de l'API de distinguer entre les problèmes dès qu'un programme tente de programmation pour corriger le problème, par exemple en se nourrissant des valeurs par défaut d'un appel, répétez!

(3) la Cartographie crée le danger de bug de masquage:Pour la carte argument des violations de contrainte dans IllegalArgumentException, vous aurez besoin de code externe try-catch au sein de chaque méthode qui a toute contrainte arguments.Cependant, il suffit d'attraper les RuntimeException dans ce bloc catch est hors de question, parce que les risques de cartographie documenté RuntimeExceptions jetés par libery méthodes utilisées au sein de la vôtre en IllegalArgumentException, même si elles ne sont pas causées par l'argument des violations de contrainte.Si vous avez besoin d'être très précis, mais même que l'effort ne vous protège pas de l'affaire que vous avez accidentellement de la carte, un sans-papier exception d'exécution d'un autre API (c'est à direun bug) dans une IllegalArgumentException de votre API.Même les plus prudents de la cartographie, par conséquent, les risques de masquage des erreurs de programmation de la librairie décideurs comme argument les violations de contraintes de votre méthode d'utilisateurs, ce qui est tout simplement hillareous comportement!

Avec la norme de la pratique d'autre part, les règles rester simple, et à l'exception des causes séjour démasqué et spécifiques.Pour la méthode de l'appelant, les règles sont simple:- si vous rencontrez un cas documenté d'exception d'exécution de tout genre, parce que vous avez passé une valeur illégale, de répéter l'appel avec une valeur par défaut (pour cela, les exceptions spécifiques sont nécessaires), ou de corriger votre code - si en revanche vous enccounter une exception d'exécution qui n'est pas documentée pour arriver à un ensemble donné d'arguments, remplir un rapport de bogue à la méthode décideurs politiques afin de s'assurer que leur code ou de leur documentation est fixe.

En général, un développeur doit jamais jeter une NullPointerException.Cette exception est levée par le moteur d'exécution lorsque le code tente de déréférencer une variable qui a la valeur null.Par conséquent, si votre méthode veut explicitement interdire null, par opposition à juste arrivé d'avoir une valeur null soulever une exception NullPointerException, vous devriez jeter un IllegalArgumentException.

Lancer une exception qui est exclusif null arguments (si NullPointerException ou un type personnalisé) automatisés null les tests plus fiables.Ce test automatisé peut être fait avec réflexion et un ensemble de valeurs par défaut, comme dans Goyave's NullPointerTester.Par exemple, NullPointerTester serait tenter 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: "", null et null, ImmutableList.of().Il permettrait de vérifier que chacun de ces appels jette l'attend NullPointerException.Pour cette mise en œuvre, le passage d'un null la liste n' pas produire NullPointerException.Il ne, cependant, arriver à produire un IllegalArgumentException parce que NullPointerTester il arrive à utiliser une valeur par défaut de la chaîne de "".Si NullPointerTester s'attend à ce que NullPointerException pour null valeurs, elle attrape le bug.Si elle s'attend IllegalArgumentException, il manque il.

Comme une question subjective, cela devrait être fermé, mais comme il est toujours ouvert:

Cela fait partie de la politique interne utilisé à mon ancien lieu de travail, et il a vraiment bien travaillé.C'est tout de mémoire, donc je ne me souviens plus de la formulation exacte.Il est intéressant de noter qu'ils n'utilisent pas vérifié exceptions, mais c'est au-delà de la portée de la question.La décoché exceptions, ils ont fait usage est tombé en 3 catégories principales.

NullPointerException:Ne pas jeter intentionnellement.De npe doivent être levée que par la machine virtuelle lors de la référence à une référence nulle.Tout l'effort possible doit être fait pour s'assurer que ce ne sont jamais jetés.@Nullable et @NotNull doit être utilisé en conjonction avec des outils d'analyse de code pour trouver ces erreurs.

IllegalArgumentException:Levée lors de l'argument à une fonction n'est pas conforme à la documentation publique, tels que l'erreur peut être identifié et décrit en termes de passage d'arguments dans.L'OP situation serait tomber dans cette catégorie.

IllegalStateException:Levée lorsqu'une fonction est appelée et ses arguments sont soit inattendue au moment où ils sont passés ou incompatible avec l'état de l'objet, la méthode est un membre de.

Par exemple, il y avait deux versions internes de la IndexOutOfBoundsException utilisé dans les choses qui avaient une longueur.Une sous-classe de l'exception IllegalStateException, utilisé si l'indice a été plus grande que la longueur.L'autre une sous-classe de IllegalArgumentException, utilisé si l'indice est négatif.C'est parce que vous pouvez ajouter d'autres éléments à l'objet et l'argument serait valable, alors qu'un nombre négatif n'est jamais valide.

Comme je l'ai dit, ce système fonctionne vraiment bien, et il a fallu quelqu'un pour expliquer pourquoi la distinction est-il:"Selon le type d'erreur, il est assez simple pour vous de comprendre quoi faire.Même si vous ne pouvez pas vraiment comprendre ce qui s'est passé, vous pouvez trouver où prendre cette erreur et d'en créer d'autres informations de débogage."

NullPointerException:Gérer la valeur Null ou de les mettre dans une affirmation de sorte que les NPE n'est pas levée.Si vous mettez dans l'affirmation est juste l'un des deux autres types.Si possible, continuer de débogage comme si cette affirmation était là en premier lieu.

IllegalArgumentException:vous avez quelque chose de mal à votre site d'appel.Si les valeurs transmises sont d'une autre fonction, savoir pourquoi vous recevez une valeur incorrecte.Si vous êtes de passage dans l'un de vos arguments propager les contrôles d'erreur en haut de la pile d'appel jusqu'à ce que vous trouver la fonction qui ne retourne pas à quoi vous vous attendez.

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

De toute façon, son point est que vous ne pouvez copier le IllegalArgumentAssertions haut de la pile.Il n'y a aucun moyen pour vous de propager la IllegalStateExceptions ou NullPointerExceptions de la pile car ils avaient quelque chose à faire avec votre fonction.

Je voulais sortir des arguments Nuls à partir d'autres illégale arguments, donc j'ai tiré une exception de l'IAE nommé NullArgumentException.Sans même avoir besoin de lire le message de l'exception, je sais qu'un argument null est passé dans une méthode et par la lecture du message, - je trouver d'argument est null.Je me surprends encore à la NullArgumentException avec l'IAE de gestionnaire, mais dans mes journaux c'est où je peux voir la différence rapidement.

la dichotomie...Sont-ils non-cumul?Seul le non-chevauchement des parties d'un ensemble peut faire une dichotomie.Comme je le vois:

throw new IllegalArgumentException(new NullPointerException(NULL_ARGUMENT_IN_METHOD_BAD_BOY_BAD));

Certaines collections supposer que null est rejeté à l'aide de NullPointerException plutôt que de IllegalArgumentException.Par exemple, si vous comparez un ensemble contenant null pour un jeu qui le rejette null, le premier s'appel containsAll sur l'autre, et de rattraper son NullPointerException - mais pas IllegalArgumentException.(Je suis à la recherche à la mise en œuvre de AbstractSet.equals.)

Vous pourriez raisonnablement faire valoir que l'utilisation incontrôlée des exceptions de cette façon est un antipattern, que la comparaison de collections qui contiennent null pour les collections qui ne peuvent pas contenir d' null est probablement un bogue qui a vraiment devrait produire une exception, ou que la mise null dans une collection à tous est une mauvaise idée.Néanmoins, si vous êtes prêt à dire que equals doit lever une exception, dans ce cas, vous êtes coincé en se souvenant que NullPointerException est nécessaire, dans certaines circonstances, mais pas dans d'autres.("De l'IAE avant de NPE sauf après le "c"...")

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

IllegalArgumentException levée lorsqu'une méthode reçoit un argument formaté différemment de la méthode attend

En fonction de votre scénario, IllegalArgumentException est le meilleur choix, parce que null n'est pas une valeur valide pour votre propriété.

Idéalement exceptions d'exécution ne doivent pas être jetés.Un checked exception(exception métier) doit être créé pour votre scénario.Parce que si ces une exception est levée et connecté, ce qui misguides le développeur en passant par les journaux.Au lieu d'affaires exceptions ne pas créer la panique et généralement ignoré lors de la résolution des journaux.

Les définitions des liens vers les deux exceptions ci-dessus sont IllegalArgumentException:Levée pour indiquer qu'une méthode a été adoptée illégale ou inappropriée de l'argument.NullPointerException:Levée lorsqu'une application tente d'utiliser la valeur null dans le cas où un objet est requis.

La grande différence ici, c'est la IllegalArgumentException est censé être utilisé lors de la vérification d'un argument à une méthode est valide.NullPointerException est censé être utilisé à chaque fois qu'un objet d'être "utilisé" quand il est nul.

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

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

Si c'est quelque chose que je vais utiliser (déréférencement) dès maintenant dans la méthode, je jette un NullPointerException de manière proactive.J'aime mieux cela que de laisser le moteur d'exécution le faire, parce que je peux fournir un utile message (on dirait que le moteur d'exécution pourrait le faire aussi, mais c'est un coup de gueule pour un autre jour).

Si je suis remplacement d'une méthode, j'utilise tout ce que la méthode de remplacement des utilisations.

Vous devriez jeter un IllegalArgumentException, comme il sera évident pour le programmeur qu'il a fait quelque chose d'incorrect.Les développeurs sont tellement habitués à voir les entrées en phase nationale lancée par la machine virtuelle, que n'importe quel programmeur ne serait pas tout de suite compte de son erreur, et permettrait de commencer à regarder autour de au hasard, ou pire, le blâme de votre code pour être "buggy".

Dans ce cas, IllegalArgumentException transmet une information claire à l'utilisateur à l'aide de votre API que le "ne doit pas être nul".Comme d'autres utilisateurs du forum a souligné que vous pourriez utiliser NPE si vous voulez aussi longtemps que vous transmettre la bonne information à l'utilisateur à l'aide de votre API.

GaryF et tweakt abandonné "Effective Java" (qui je le jure par les références qui recommande l'utilisation des NPE.Et en regardant comment les autres bonnes Api sont construits est la meilleure façon de voir comment construire votre API.

Un autre bon exemple est de regarder le Printemps de l'Api.Par exemple, org.springframework.les haricots.BeanUtils.instantiateClass(Constructeur ctor, Object[] args) a un faire Valoir.notNull(ctor, "Constructeur ne doit pas être null") de la ligne.org.springframework.util.Affirmer.notNull(Object Object, String message) méthode vérifie si l'argument (objet) transmis est nulle et si il est il jette un new IllegalArgumentException(message) qui est alors pris dans le org.springframework.les haricots.BeanUtils.instantiateClass(...) de la méthode.

Si vous choisissez de jeter un NPE et vous êtes à l'aide de l'argument dans votre méthode, il peut être redondants et coûteux explicitement vérifier pour une valeur nulle.Je pense que la VM déjà fait pour vous.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top