J'utilise object != null
beaucoup pour éviter NullPointerException
.
Y a-t-il une bonne alternative à cela?
Par exemple, j'utilise souvent:
if (someobject != null) {
someobject.doCalc();
}
Cela recherche un NullPointerException
pour l' someobject
objet dans l'extrait ci-dessus.
Notez que la réponse acceptée peut être obsolète, voir https://stackoverflow.com/a/2386013/12943 pour une approche plus récente.
java
object
nullpointerexception
null
Goran Martinic
la source
la source
Option
type génial de Scala est entaché par la réticence du langage à contrôler ou à interdirenull
. J'ai mentionné cela sur hackernews et j'ai été rétrogradé et j'ai dit que "personne n'utilise null dans Scala de toute façon". Devinez quoi, je trouve déjà des null dans Scala écrit par un collègue. Oui, ils "le font mal" et doivent être éduqués à ce sujet, mais le fait demeure que le système de type de la langue devrait me protéger de cela et ce n'est pas le cas :(Réponses:
Pour moi, cela ressemble à un problème assez courant auquel les développeurs juniors à intermédiaires ont tendance à faire face à un moment donné: ils ne connaissent pas ou ne font pas confiance aux contrats auxquels ils participent et vérifient de manière défensive les null. De plus, lors de l'écriture de leur propre code, ils ont tendance à compter sur le retour de null pour indiquer quelque chose, ce qui oblige l'appelant à vérifier les null.
Pour le dire autrement, il y a deux cas où la vérification nulle apparaît:
Lorsque null est une réponse valable en termes de contrat; et
Où ce n'est pas une réponse valide.
(2) est facile. Utilisez des
assert
instructions (assertions) ou autorisez l'échec (par exemple, NullPointerException ). Les assertions sont une fonctionnalité Java très sous-utilisée qui a été ajoutée dans 1.4. La syntaxe est:ou
où
<condition>
est une expression booléenne et<object>
est un objet donttoString()
la sortie de la méthode sera incluse dans l'erreur.Une
assert
instruction renvoie unError
(AssertionError
) si la condition n'est pas vraie. Par défaut, Java ignore les assertions. Vous pouvez activer les assertions en transmettant l'option-ea
à la JVM. Vous pouvez activer et désactiver les assertions pour des classes et des packages individuels. Cela signifie que vous pouvez valider le code avec les assertions lors du développement et des tests et les désactiver dans un environnement de production, bien que mes tests n'aient montré pratiquement aucun impact sur les performances des assertions.Ne pas utiliser d'assertions dans ce cas est correct car le code échouera, ce qui se produira si vous utilisez des assertions. La seule différence est qu'avec les assertions, cela pourrait arriver plus tôt, d'une manière plus significative et éventuellement avec des informations supplémentaires, ce qui pourrait vous aider à comprendre pourquoi cela s'est produit si vous ne vous y attendiez pas.
(1) est un peu plus difficile. Si vous n'avez aucun contrôle sur le code que vous appelez, vous êtes bloqué. Si null est une réponse valide, vous devez la vérifier.
Si c'est du code que vous contrôlez cependant (et c'est souvent le cas), alors c'est une autre histoire. Évitez d'utiliser des valeurs nulles comme réponse. Avec les méthodes qui retournent des collections, c'est facile: renvoyez des collections vides (ou tableaux) au lieu de null à peu près tout le temps.
Avec des non-collections, cela pourrait être plus difficile. Considérez ceci comme un exemple: si vous avez ces interfaces:
où Parser prend les entrées utilisateur brutes et trouve quelque chose à faire, peut-être si vous implémentez une interface de ligne de commande pour quelque chose. Vous pouvez maintenant rendre le contrat qu'il renvoie nul s'il n'y a aucune action appropriée. Cela mène à la vérification nulle dont vous parlez.
Une solution alternative consiste à ne jamais retourner null et à utiliser à la place le modèle Null Object :
Comparer:
à
ce qui est une bien meilleure conception car elle conduit à un code plus concis.
Cela dit, il est peut-être tout à fait approprié que la méthode findAction () lève une exception avec un message d'erreur significatif - en particulier dans ce cas où vous comptez sur une entrée utilisateur. Il serait beaucoup mieux pour la méthode findAction de lever une exception que pour la méthode appelante de sauter avec une simple NullPointerException sans explication.
Ou si vous pensez que le mécanisme try / catch est trop laid, plutôt que Ne rien faire, votre action par défaut devrait fournir des commentaires à l'utilisateur.
la source
Si vous utilisez (ou prévoyez d'utiliser) un IDE Java comme JetBrains IntelliJ IDEA , Eclipse ou Netbeans ou un outil comme findbugs, vous pouvez utiliser des annotations pour résoudre ce problème.
Fondamentalement, vous avez
@Nullable
et@NotNull
.Vous pouvez utiliser dans la méthode et les paramètres, comme ceci:
ou
Le deuxième exemple ne se compilera pas (dans IntelliJ IDEA).
Lorsque vous utilisez la première
helloWorld()
fonction dans un autre morceau de code:Maintenant, le compilateur IntelliJ IDEA vous dira que la vérification est inutile, car la
helloWorld()
fonction ne reviendranull
jamais.Utilisation d'un paramètre
si vous écrivez quelque chose comme:
Cela ne se compilera pas.
Dernier exemple utilisant
@Nullable
Ce faisant
Et vous pouvez être sûr que cela n'arrivera pas. :)
C'est un bon moyen de laisser le compilateur vérifier quelque chose de plus qu'il ne le fait habituellement et de faire en sorte que vos contrats soient plus forts. Malheureusement, il n'est pas pris en charge par tous les compilateurs.
Dans IntelliJ IDEA 10.5 et versions ultérieures, ils ont ajouté la prise en charge de toutes les autres
@Nullable
@NotNull
implémentations.Voir l'article de blog Annotations @ Nullable / @ NotNull plus flexibles et configurables .
la source
@NotNull
,@Nullable
Et d' autres annotations font partie de l' état NULL JSR 305 . Vous pouvez également les utiliser pour détecter des problèmes potentiels avec des outils comme FindBugs .@NotNull
&@Nullable
vivent dans le packagecom.sun.istack.internal
. (Je suppose que j'associe com.sun aux avertissements concernant l'utilisation d'une API propriétaire.)@NotNull
et@Nullable
sont qu'elles se dégradent bien lorsque le code source est construit par un système qui ne les comprend pas. Ainsi, en effet, l'argument selon lequel le code n'est pas portable peut être invalide - si vous utilisez un système qui prend en charge et comprend ces annotations, vous obtenez l'avantage supplémentaire d'une vérification d'erreur plus stricte, sinon vous en obtenez moins mais votre code devrait quand même build fine, et la qualité de votre programme en cours d'exécution est LA MÊME, car ces annotations n'ont pas été appliquées lors de l'exécution de toute façon. De plus, tous les compilateurs sont personnalisés ;-)Si les valeurs nulles ne sont pas autorisées
Si votre méthode est appelée en externe, commencez par quelque chose comme ceci:
Ensuite, dans le reste de cette méthode, vous saurez que ce
object
n'est pas nul.S'il s'agit d'une méthode interne (ne faisant pas partie d'une API), documentez simplement qu'elle ne peut pas être nulle, et c'est tout.
Exemple:
Cependant, si votre méthode transmet simplement la valeur et que la méthode suivante la transmet, etc., cela peut devenir problématique. Dans ce cas, vous pouvez vérifier l'argument comme ci-dessus.
Si null est autorisé
Cela dépend vraiment. Si je trouve que je fais souvent quelque chose comme ça:
Je branche donc et fais deux choses complètement différentes. Il n'y a pas d'extrait de code laid, car j'ai vraiment besoin de faire deux choses différentes en fonction des données. Par exemple, dois-je travailler sur l'entrée ou dois-je calculer une bonne valeur par défaut?
Il est en fait rare que j'utilise l'idiome "
if (object != null && ...
".Il peut être plus facile de vous donner des exemples si vous montrez des exemples où vous utilisez généralement l'idiome.
la source
throw new IllegalArgumentException("object==null")
Wow, je déteste presque ajouter une autre réponse lorsque nous avons 57 façons différentes de recommander le
NullObject pattern
, mais je pense que certaines personnes intéressées par cette question aimeraient savoir qu'il y a une proposition sur la table pour Java 7 d'ajouter "null-safe" manipulation " - une syntaxe simplifiée pour la logique if-not-equal-null.L'exemple donné par Alex Miller ressemble à ceci:
Le
?.
moyen ne dé-référence l'identifiant gauche que s'il n'est pas nul, sinon évaluez le reste de l'expression commenull
. Certaines personnes, comme le membre de Java Posse, Dick Wall, et les électeurs de Devoxx aiment vraiment cette proposition, mais il y a aussi une opposition, au motif qu'elle encouragera en fait une plus grande utilisation de lanull
valeur sentinelle.Mise à jour: une proposition officielle pour un opérateur null-safe dans Java 7 a été soumise sous Project Coin. La syntaxe est un peu différente de l'exemple ci-dessus, mais c'est la même notion.
Mise à jour: la proposition d'opérateur null-safe n'est pas entrée dans Project Coin. Vous ne verrez donc pas cette syntaxe dans Java 7.
la source
Si les valeurs non définies ne sont pas autorisées:
Vous pouvez configurer votre IDE pour vous avertir d'un éventuel déréférencement nul. Par exemple, dans Eclipse, voir Préférences> Java> Compilateur> Erreurs / Avertissements / Analyse nulle .
Si des valeurs non définies sont autorisées:
Si vous souhaitez définir une nouvelle API où les valeurs non définies ont un sens , utilisez le modèle d'option (peut être familier des langages fonctionnels). Il présente les avantages suivants:
Java 8 a une
Optional
classe intégrée (recommandée); pour les versions antérieures, il existe des alternatives bibliothèque, par exemple goyave « sOptional
ou FunctionalJava d »Option
. Mais comme de nombreux modèles de style fonctionnel, l'utilisation d'Option en Java (même 8) donne lieu à un certain nombre de références, que vous pouvez réduire en utilisant un langage JVM moins verbeux, par exemple Scala ou Xtend.Si vous devez gérer une API qui peut renvoyer des valeurs nulles , vous ne pouvez pas faire grand-chose en Java. Xtend et Groovy ont l' opérateur Elvis
?:
et l' opérateur de déréférence null-safe?.
, mais notez que cela retourne null dans le cas d'une référence null, donc il "diffère" juste le traitement correct de null.la source
Seulement pour cette situation -
Ne pas vérifier si une variable est nulle avant d'invoquer une méthode equals (un exemple de comparaison de chaîne ci-dessous):
entraînera un
NullPointerException
sifoo
n'existe pas.Vous pouvez éviter cela si vous comparez les vôtres
String
comme ceci:la source
<object that you know that is not null>.equals(<object that might be null>);
. Cela fonctionne pour d'autres méthodes queequals
si vous connaissez le contrat et que ces méthodes peuvent gérer lesnull
paramètres.Avec Java 8 vient la nouvelle
java.util.Optional
classe qui résout sans doute une partie du problème. On peut au moins dire que cela améliore la lisibilité du code et, dans le cas des API publiques, rendre le contrat de l'API plus clair pour le développeur client.Ils fonctionnent comme ça:
Un objet facultatif pour un type donné (
Fruit
) est créé comme type de retour d'une méthode. Il peut être vide ou contenir unFruit
objet:Regardez maintenant ce code où nous recherchons une liste de
Fruit
(fruits
) pour une instance de Fruit donnée:Vous pouvez utiliser l'
map()
opérateur pour effectuer un calcul sur - ou extraire une valeur - d'un objet facultatif.orElse()
vous permet de remplacer les valeurs manquantes.Bien sûr, la vérification de la valeur nulle / vide est toujours nécessaire, mais au moins le développeur est conscient que la valeur peut être vide et le risque d'oublier de vérifier est limité.
Dans une API construite à partir de zéro en utilisant
Optional
chaque fois qu'une valeur de retour peut être vide, et en renvoyant un objet simple uniquement lorsqu'il ne peut pas l'êtrenull
(convention), le code client peut abandonner les vérifications nulles sur les valeurs de retour d'objet simples ...Bien sûr,
Optional
pourrait également être utilisé comme argument de méthode, peut-être un meilleur moyen d'indiquer des arguments facultatifs que 5 ou 10 méthodes de surcharge dans certains cas.Optional
propose d'autres méthodes pratiques, telles que cellesorElse
qui permettent l'utilisation d'une valeur par défaut, etifPresent
qui fonctionnent avec les expressions lambda .Je vous invite à lire cet article (ma principale source d'écriture de cette réponse) dans lequel la
NullPointerException
problématique (et en général le pointeur nul) ainsi que la solution (partielle) apportéeOptional
sont bien expliquées: Java Optional Objects .la source
if(optional.isPresent()){ optional.get(); }
au lieu deoptional.ifPresent(o -> { ...})
Selon le type d'objets que vous vérifiez, vous pourrez peut-être utiliser certaines des classes dans les collections apache commons telles que: collections apache commons lang et apache commons
Exemple:
ou (selon ce que vous devez vérifier):
La classe StringUtils n'est que l'une des nombreuses; il y a pas mal de bonnes classes dans les communs qui font des manipulations sûres nulles.
Voici un exemple de la façon dont vous pouvez utiliser la vallidation nulle dans JAVA lorsque vous incluez la bibliothèque apache (commons-lang-2.4.jar)
Et si vous utilisez Spring, Spring a également la même fonctionnalité dans son package, voir bibliothèque (spring-2.4.6.jar)
Exemple d'utilisation de cette classe statique à partir du printemps (org.springframework.util.Assert)
la source
Vous devez vérifier l'objet! = Null uniquement si vous voulez gérer le cas où l'objet peut être nul ...
Il est proposé d'ajouter de nouvelles annotations dans Java7 pour aider avec les paramètres null / notnull: http://tech.puredanger.com/java7/#jsr308
la source
Je suis fan du code "fail fast". Demandez-vous - faites-vous quelque chose d'utile dans le cas où le paramètre est nul? Si vous n'avez pas de réponse claire à ce que votre code devrait faire dans ce cas ... C'est-à-dire qu'il ne devrait jamais être nul en premier lieu, alors ignorez-le et autorisez une NullPointerException à être levée. Le code appelant aura autant de sens pour un NPE que pour une exception IllegalArgumentException, mais il sera plus facile pour le développeur de déboguer et de comprendre ce qui s'est passé si un NPE est lancé plutôt que votre code tentant d'exécuter une autre contingence inattendue logique - ce qui entraîne finalement l'échec de l'application de toute façon.
la source
Le cadre des collections Google offre un moyen efficace et élégant de réaliser la vérification nulle.
Il existe une méthode dans une classe de bibliothèque comme celle-ci:
Et l'utilisation est (avec
import static
):Ou dans votre exemple:
la source
getThing().getItsThing().getOtherThing().wowEncapsulationIsBroken().setLol("hi");
Parfois, vous avez des méthodes qui opèrent sur ses paramètres qui définissent une opération symétrique:
Si vous savez que b ne peut jamais être nul, vous pouvez simplement l'échanger. Il est très utile pour les égaux: au lieu de
foo.equals("bar");
faire mieux"bar".equals(foo);
.la source
equals
(pourrait être n'importe quelle méthode) que Null sera correctement géré. Vraiment, tout cela consiste à passer la responsabilité à quelqu'un d'autre (ou à une autre méthode).equals
(ou quelle que soit la méthode) doit vérifier denull
toute façon. Ou déclarez explicitement que non.Plutôt que Null Object Pattern - qui a ses utilisations - vous pourriez envisager des situations où l'objet nul est un bogue.
Lorsque l'exception est levée, examinez la trace de la pile et résolvez le bogue.
la source
Null n'est pas un «problème». Il fait partie intégrante d'un ensemble complet d' outils de modélisation. Le logiciel vise à modéliser la complexité du monde et null porte son fardeau. Null indique «Aucune donnée» ou «Inconnu» en Java et similaires. Il est donc approprié d'utiliser des valeurs nulles à ces fins. Je ne préfère pas le motif «objet nul»; Je pense que cela soulève le problème « qui gardera les gardiens ».
Si vous me demandez quel est le nom de ma petite amie, je vous dirai que je n'ai pas de petite amie. Dans le langage Java, je retournerai null. Une alternative serait de lever une exception significative pour indiquer un problème qui ne peut pas être (ou ne pas ''
Pour une «question inconnue», donnez «réponse inconnue». (Assurez-vous que la valeur NULL est correcte du point de vue commercial) La vérification des arguments NULL une fois à l'intérieur d'une méthode avant utilisation évite à plusieurs appelants de les vérifier avant un appel.
Le précédent conduit à un flux logique normal pour ne pas obtenir de photo d'une petite amie inexistante de ma photothèque.
Et il correspond à la nouvelle API Java à venir (pour l'avenir)
Bien qu'il soit plutôt `` flux commercial normal '' de ne pas trouver de photo stockée dans la base de données pour une personne, j'ai utilisé des paires comme ci-dessous pour d'autres cas
Et ne détestez pas taper
<alt> + <shift> + <j>
(générer javadoc dans Eclipse) et écrire trois mots supplémentaires pour votre API publique. Ce sera plus que suffisant pour tous, sauf pour ceux qui ne lisent pas la documentation.ou
C'est un cas plutôt théorique et dans la plupart des cas, vous devriez préférer l'API java null safe (au cas où elle serait publiée dans 10 ans), mais
NullPointerException
c'est une sous-classe d'unException
. C'est donc une formeThrowable
qui indique les conditions qu'une application raisonnable pourrait vouloir attraper ( javadoc )! Pour utiliser le premier avantage des exceptions et séparer le code de gestion des erreurs du code «normal» ( selon les créateurs de Java ), il est approprié, comme pour moi, d'attraperNullPointerException
.Des questions pourraient se poser:
Q. Et si
getPhotoDataSource()
renvoie null?R. Cela dépend de la logique métier. Si je ne trouve pas d'album photo, je ne vous montrerai aucune photo. Que faire si appContext n'est pas initialisé? La logique métier de cette méthode supporte cela. Si la même logique doit être plus stricte que de lancer une exception, elle fait partie de la logique métier et une vérification explicite de null doit être utilisée (cas 3). La nouvelle API Java Null-safe s'adapte mieux ici pour spécifier sélectivement ce qui implique et ce qui n'implique pas d'être initialisé pour être rapide en cas d'erreurs de programmation.
Q. Du code redondant pourrait être exécuté et des ressources inutiles pourraient être récupérées.
A. Cela pourrait avoir lieu si
getPhotoByName()
j'essayais d'ouvrir une connexion à une base de données, de créerPreparedStatement
et d'utiliser enfin le nom de la personne comme paramètre SQL. L'approche pour une question inconnue donne une réponse inconnue (cas 1) fonctionne ici. Avant de récupérer des ressources, la méthode doit vérifier les paramètres et retourner un résultat «inconnu» si nécessaire.Q. Cette approche a une pénalité de performance en raison de l'ouverture de fermeture d'essai.
A. Le logiciel doit être facile à comprendre et à modifier en premier lieu. Ce n'est qu'après cela que l'on pourrait penser aux performances, et seulement si nécessaire! et là où c'est nécessaire! ( source ), et bien d'autres).
PS. Cette approche sera aussi raisonnable à utiliser que le code de gestion d'erreurs distinct du principe de code "normal" est raisonnable à utiliser à un certain endroit. Prenons l'exemple suivant:
PPS. Pour ceux qui souhaitent voter rapidement (et pas si rapidement pour lire la documentation), je voudrais dire que je n'ai jamais détecté d'exception de pointeur nul (NPE) dans ma vie. Mais cette possibilité a été intentionnellement conçue par les créateurs Java car NPE est une sous-classe de
Exception
. Nous avons un précédent dans l'histoire de Java quand ceThreadDeath
n'estError
pas le cas car il s'agit en fait d'une erreur d'application, mais uniquement parce qu'il n'était pas destiné à être rattrapé! Combien de NPE convient pour être unError
queThreadDeath
! Mais ce n'est pas.Cochez «Aucune donnée» uniquement si la logique métier le sous-entend.
et
Si appContext ou dataSource n'est pas initialisé, le runtime non géré NullPointerException tuera le thread actuel et sera traité par Thread.defaultUncaughtExceptionHandler (pour que vous puissiez définir et utiliser votre enregistreur préféré ou un autre mécanisme de notification). S'il n'est pas défini, ThreadGroup # uncaughtException imprime stacktrace à l'erreur système. Il faut surveiller le journal des erreurs d'application et ouvrir le problème Jira pour chaque exception non gérée qui est en fait une erreur d'application. Le programmeur devrait corriger le bogue quelque part dans les trucs d'initialisation.
la source
NullPointerException
et retournernull
est horrible à déboguer. Vous vous retrouvez avec NPE plus tard de toute façon, et il est vraiment difficile de comprendre ce qui était initialement nul.if (maybeNull.hasValue()) {...}
ça, alors quelle est la différence avecif (maybeNull != null)) {...}
?Maybe<T>
ouOptional<T>
n'est pas dans le cas où votreT
pourrait être nul, mais dans le cas où il ne devrait jamais être nul. Si vous avez un type qui signifie explicitement "cette valeur peut être nulle - utilisez avec prudence", et que vous utilisez et renvoyez un tel type de manière cohérente, chaque fois que vous voyez un ancien simpleT
dans votre code, vous pouvez supposer qu'il n'est jamais nul. (Java 7 a une nouvelle
java.util.Objects
classe utilitaire sur laquelle il existe unerequireNonNull()
méthode. Tout cela ne fait que lancer unNullPointerException
si son argument est nul, mais il nettoie un peu le code. Exemple:La méthode est très utile pour vérifier juste avant une affectation dans un constructeur, où chaque utilisation de celle-ci peut enregistrer trois lignes de code:
devient
la source
doCalc(someObject)
.doCalc()
, et qu'il ne lance pas immédiatement NPE lorsqu'il est nul, vous devez vérifier pour null et lancer NPE vous-même. C'est pour çaObjects.requireNonNull()
.En fin de compte, la seule façon de résoudre complètement ce problème est d'utiliser un langage de programmation différent:
nil
et absolument rien ne se passera. Cela rend la plupart des contrôles nuls inutiles, mais cela peut rendre les erreurs beaucoup plus difficiles à diagnostiquer.la source
"Problème" commun en Java en effet.
Tout d'abord, mes réflexions à ce sujet:
Je considère qu'il est mauvais de "manger" quelque chose lorsque NULL a été passé alors que NULL n'est pas une valeur valide. Si vous ne quittez pas la méthode avec une sorte d'erreur, cela signifie que rien ne s'est mal passé dans votre méthode, ce qui n'est pas vrai. Ensuite, vous retournez probablement null dans ce cas, et dans la méthode de réception, vous vérifiez à nouveau pour null, et cela ne se termine jamais, et vous vous retrouvez avec "if! = Null", etc.
Donc, à mon humble avis, null doit être une erreur critique qui empêche toute exécution ultérieure (c'est-à-dire où null n'est pas une valeur valide).
La façon dont je résous ce problème est la suivante:
Tout d'abord, je respecte cette convention:
Et enfin, dans le code, la première ligne de la méthode publique se présente comme suit:
Notez que addParam () renvoie self, afin que vous puissiez ajouter plus de paramètres à vérifier.
La méthode
validate()
lancera vérifiéValidationException
si l'un des paramètres est nul (coché ou décoché est plus un problème de conception / goût, mais monValidationException
est vérifié).Le message contiendra le texte suivant si, par exemple, "plans" est nul:
"Une valeur d'argument non valide est rencontrée pour le paramètre [plans] "
Comme vous pouvez le voir, la deuxième valeur de la méthode (chaîne) addParam () est nécessaire pour le message utilisateur, car vous ne pouvez pas facilement détecter le nom de variable transmise, même avec réflexion (de toute façon pas l'objet de cet article ...).
Et oui, nous savons qu'au-delà de cette ligne, nous ne rencontrerons plus de valeur nulle, nous invoquons donc en toute sécurité des méthodes sur ces objets.
De cette façon, le code est propre, facile à entretenir et lisible.
la source
Poser cette question indique que vous pourriez être intéressé par les stratégies de gestion des erreurs. L'architecte de votre équipe doit décider de la façon de traiter les erreurs. Il y a plusieurs moyens de le faire:
permettre aux exceptions de se propager à travers - les attraper à la «boucle principale» ou dans une autre routine de gestion.
Bien sûr, jetez également un œil à la programmation orientée aspect - ils ont des façons intéressantes d'insérer
if( o == null ) handleNull()
dans votre bytecode.la source
En plus d'utiliser,
assert
vous pouvez utiliser les éléments suivants:C'est légèrement mieux que:
la source
if (!something) { x(); } else { y(); }
je serais enclin à le refactoriserif (something) { y(); } else { x(); }
(bien que l'on puisse dire que!= null
c'est l'option la plus positive ...). Mais plus important encore, la partie importante du code n'est pas encapsulée à l'intérieur de{}
s et vous avez un niveau de retrait de moins pour la plupart de la méthode. Je ne sais pas si c'était le raisonnement de fastcodejava mais ce serait le mien.N'utilisez jamais null. Ne le permettez pas.
Dans mes classes, la plupart des champs et des variables locales ont des valeurs par défaut non nulles, et j'ajoute des déclarations de contrat (assertions toujours actives) partout dans le code pour s'assurer que cela est appliqué (car c'est plus succinct et plus expressif que de le laisser) venir comme un NPE et ensuite avoir à résoudre le numéro de ligne, etc.).
Une fois que j'ai adopté cette pratique, j'ai remarqué que les problèmes semblaient se régler. Vous attraperiez les choses beaucoup plus tôt dans le processus de développement juste par accident et vous vous rendriez compte que vous aviez un point faible .. et plus important encore .. cela aide à résumer les préoccupations des différents modules, différents modules peuvent se `` faire confiance '' les uns les autres, et ne jonchent plus les code avec
if = null else
constructions!Il s'agit d'une programmation défensive et se traduit par un code beaucoup plus propre à long terme. Nettoyez toujours les données, par exemple ici en appliquant des normes rigides, et les problèmes disparaissent.
Les contrats sont comme des mini-tests unitaires qui sont toujours en cours, même en production, et quand les choses échouent, vous savez pourquoi, plutôt qu'un NPE aléatoire, vous devez en quelque sorte comprendre.
la source
Guava, une bibliothèque de base très utile de Google, possède une API agréable et utile pour éviter les null. Je trouve UsingAndAvoidingNullExplained très utile.
Comme expliqué dans le wiki:
Usage:
la source
Il s'agit d'un problème très courant pour tous les développeurs Java. Il existe donc un support officiel dans Java 8 pour résoudre ces problèmes sans code encombré.
Java 8 a introduit
java.util.Optional<T>
. Il s'agit d'un conteneur qui peut contenir ou non une valeur non nulle. Java 8 a donné un moyen plus sûr de gérer un objet dont la valeur peut être nulle dans certains cas. Il est inspiré des idées de Haskell et Scala .En un mot, la classe Optional inclut des méthodes pour traiter explicitement les cas où une valeur est présente ou absente. Cependant, l'avantage par rapport aux références nulles est que la classe Facultatif <T> vous oblige à réfléchir au cas où la valeur n'est pas présente. Par conséquent, vous pouvez empêcher les exceptions de pointeur nul involontaires.
Dans l'exemple ci-dessus, nous avons une usine de service à domicile qui renvoie une poignée à plusieurs appareils disponibles dans la maison. Mais ces services peuvent être ou ne pas être disponibles / fonctionnels; cela signifie que cela peut entraîner une exception NullPointerException. Au lieu d'ajouter un null
if
condition avant d'utiliser un service, encapsulons-la dans <Service> facultatif.EMBALLAGE À L'OPTION <T>
Considérons une méthode pour obtenir une référence d'un service d'une usine. Au lieu de renvoyer la référence de service, enveloppez-la avec Facultatif. Il permet à l'utilisateur de l'API de savoir que le service retourné peut ou non être disponible / fonctionnel, utiliser de manière défensive
Comme vous le voyez,
Optional.ofNullable()
fournit un moyen facile d'obtenir la référence encapsulée. Il existe un autre moyen d'obtenir la référence de Facultatif, soitOptional.empty()
&Optional.of()
. L'une pour renvoyer un objet vide au lieu de réaccorder null et l'autre pour encapsuler un objet non nullable, respectivement.AINSI COMMENT EXACTEMENT IL AIDE À ÉVITER UN CHÈQUE NUL?
Une fois que vous avez encapsulé un objet de référence, Optional fournit de nombreuses méthodes utiles pour appeler des méthodes sur une référence encapsulée sans NPE.
Facultatif.ifPresent appelle le consommateur donné avec une référence s'il s'agit d'une valeur non nulle. Sinon, cela ne fait rien.
Représente une opération qui accepte un seul argument d'entrée et ne renvoie aucun résultat. Contrairement à la plupart des autres interfaces fonctionnelles, Consumer devrait fonctionner via des effets secondaires. C'est tellement propre et facile à comprendre. Dans l'exemple de code ci-dessus,
HomeService.switchOn(Service)
obtient invoqué si la référence de détention facultative n'est pas nulle.Nous utilisons l'opérateur ternaire très souvent pour vérifier la condition nulle et renvoyer une valeur alternative ou une valeur par défaut. Facultatif fournit une autre façon de gérer la même condition sans vérifier null. Optional.orElse (defaultObj) renvoie defaultObj si l'Optional a une valeur nulle. Utilisons ceci dans notre exemple de code:
Maintenant, HomeServices.get () fait la même chose, mais d'une meilleure façon. Il vérifie si le service est déjà initialisé ou non. Si c'est le cas, renvoyez-le ou créez un nouveau nouveau service. <T> .orElse (T) facultatif permet de renvoyer une valeur par défaut.
Enfin, voici notre NPE ainsi que le code sans vérification nul:
Le message complet est NPE ainsi que le code sans chèque Null… Vraiment? .
la source
if(homeServices != null) {
qui peut être changé enhomeServices.ifPresent(h -> //action)
;J'aime les articles de Nat Pryce. Voici les liens:
Dans les articles, il existe également un lien vers un référentiel Git pour un type Java peut-être que je trouve intéressant, mais je ne pense pas que cela puisse à lui seul diminuer le gonflement du code de vérification. Après avoir fait quelques recherches sur Internet, je pense que ! = Le gonflement du code nul pourrait être diminué principalement par une conception soignée.
la source
J'ai essayé le
NullObjectPattern
mais pour moi ce n'est pas toujours la meilleure voie à suivre. Il y a parfois un "pas d'action" qui n'est pas approprié.NullPointerException
est une exception Runtime qui signifie que c'est la faute des développeurs et avec suffisamment d'expérience, il vous indique exactement où est l'erreur.Passons maintenant à la réponse:
Essayez de rendre tous vos attributs et ses accesseurs aussi privés que possible ou évitez de les exposer aux clients. Vous pouvez bien sûr avoir les valeurs d'argument dans le constructeur, mais en réduisant la portée, vous ne laissez pas la classe client passer une valeur non valide. Si vous devez modifier les valeurs, vous pouvez toujours en créer une nouvelle
object
. Vous ne vérifiez les valeurs dans le constructeur qu'une seule fois et dans les autres méthodes, vous pouvez être presque sûr que les valeurs ne sont pas nulles.Bien sûr, l'expérience est la meilleure façon de comprendre et d'appliquer cette suggestion.
Octet!
la source
La meilleure alternative pour Java 8 ou plus récent est probablement d'utiliser la
Optional
classe.Ceci est particulièrement pratique pour les longues chaînes de valeurs nulles possibles. Exemple:
Exemple sur la façon de lever une exception sur null:
Java 7 a introduit la
Objects.requireNonNull
méthode qui peut être utile lorsque quelque chose doit être vérifié pour la non-nullité. Exemple:la source
Puis-je y répondre de manière plus générale!
Nous rencontrons généralement ce problème lorsque les méthodes obtiennent les paramètres comme nous ne nous y attendions pas (un mauvais appel de méthode est la faute du programmeur). Par exemple: vous vous attendez à obtenir un objet, au lieu de cela, vous obtenez un null. Vous vous attendez à obtenir une chaîne avec au moins un caractère, au lieu de cela, vous obtenez une chaîne vide ...
Il n'y a donc pas de différence entre:
}
ou
Ils veulent tous les deux s'assurer que nous avons reçu des paramètres valides, avant de faire d'autres fonctions.
Comme mentionné dans certaines autres réponses, pour éviter les problèmes ci-dessus, vous pouvez suivre le modèle de conception par contrat . Veuillez consulter http://en.wikipedia.org/wiki/Design_by_contract .
Pour implémenter ce modèle en java, vous pouvez utiliser des annotations java de base comme javax.annotation.NotNull ou utiliser des bibliothèques plus sophistiquées comme Hibernate Validator .
Juste un échantillon:
Maintenant, vous pouvez développer en toute sécurité la fonction de base de votre méthode sans avoir à vérifier les paramètres d'entrée, ils protègent vos méthodes des paramètres inattendus.
Vous pouvez aller plus loin et vous assurer que seuls les pojos valides peuvent être créés dans votre application. (échantillon du site de validation d'hibernation)
la source
javax
est, par définition, pas « noyau Java ».J'ignore fortement les réponses qui suggèrent d'utiliser les objets nuls dans toutes les situations. Ce modèle peut rompre le contrat et enfouir les problèmes de plus en plus profonds au lieu de les résoudre, sans mentionner que l'utilisation inappropriée créera une autre pile de code passe-partout qui nécessitera une maintenance future.
En réalité, si quelque chose renvoyé par une méthode peut être nul et que le code appelant doit prendre une décision à ce sujet, il devrait y avoir un appel antérieur qui garantit l'état.
Gardez également à l'esprit que ce modèle d'objet nul sera gourmand en mémoire s'il est utilisé sans précaution. Pour cela - l'instance d'un NullObject doit être partagée entre les propriétaires et ne pas être une instance unigue pour chacun d'eux.
De plus, je ne recommanderais pas d'utiliser ce modèle où le type est censé être une représentation de type primitif - comme des entités mathématiques, qui ne sont pas des scalaires: vecteurs, matrices, nombres complexes et objets POD (Plain Old Data), qui sont destinés à contenir l'état sous forme de types intégrés Java. Dans ce dernier cas, vous finirez par appeler des méthodes getter avec des résultats arbitraires. Par exemple, que doit renvoyer une méthode NullPerson.getName ()?
Cela vaut la peine d'envisager de tels cas afin d'éviter des résultats absurdes.
la source
Faire cela dans votre propre code et vous pouvez éviter les contrôles! = Null.
La plupart du temps, les contrôles nuls semblent protéger les boucles sur les collections ou les tableaux, alors initialisez-les simplement vides, vous n'aurez pas besoin de contrôles nuls.
Il y a une petite surcharge, mais cela en vaut la peine pour un code plus propre et moins d'exceptions NullPointerExceptions.
la source
Il s'agit de l'erreur la plus courante survenue pour la plupart des développeurs.
Nous avons plusieurs façons de gérer cela.
Approche 1:
notNull (objet Object, message String)
Approche 2:
Approche 3:
Approche 4:
la source
la source
ObjectUtils.defaultIfNull()
. Il y en a un de plus généralObjectUtils.firstNonNull()
firstNonNull(bestChoice, secondBest, thirdBest, fallBack);