J'ai noté que de nombreuses méthodes Java 8 dans Oracle JDK utilisent Objects.requireNonNull()
, ce qui déclenche en interne NullPointerException
si l'objet (argument) donné l'est null
.
public static <T> T requireNonNull(T obj) {
if (obj == null)
throw new NullPointerException();
return obj;
}
Mais NullPointerException
sera jeté de toute façon si un null
objet est déréférencé. Alors, pourquoi devrait-on faire ce check and throw nul supplémentaire
NullPointerException
?
Une réponse évidente (ou avantage) est qu'elle rend le code plus lisible et je suis d'accord. Je suis désireux de connaître d'autres raisons d'utiliser
Objects.requireNonNull()
au début de la méthode.
java
java-8
nullpointerexception
user4686046
la source
la source
Objects.requireNonNull
, votre code n'a pas de branchement, donc un seul passage d'un test unitaire vous permettra d'obtenir une couverture à 100% :-)Réponses:
Parce que vous pouvez rendre les choses explicites en le faisant. Comme:
Ou plus court:
Vous savez maintenant :
new()
Comparez cela à: vous créez un objet Foo aujourd'hui, et demain vous invoquez une méthode qui utilise ce champ et lance. Très probablement, vous ne saurez pas demain pourquoi cette référence était nulle hier lorsqu'elle a été transmise au constructeur!
En d'autres termes: en utilisant explicitement cette méthode pour vérifier les références entrantes, vous pouvez contrôler le moment où l'exception sera levée. Et la plupart du temps, vous voulez échouer le plus vite possible !
Les principaux avantages sont:
bar
n'est pas nul - et donc vous n'avez pas besoin deif (bar == null)
vérification dans d'autres endroits!la source
this.bar = Objects.requireNonNull(bar, "bar must not be null");
Objects.requireNonNull(bar, "bar must not be null");
. Merci pour celui-ci.this.bar = Objects.requireNonNull(bar, "bar must not be null");
est correct dans les constructeurs, mais potentiellement dangereux dans d'autres méthodes si deux ou plusieurs variables sont définies dans la même méthode. Exemple: talkwards.com/2018/11/03/…Rapide
Le code devrait planter dès que possible. Il ne doit pas faire la moitié du travail, puis déréférencer la valeur nulle et planter, puis laisser la moitié du travail effectué, ce qui rend le système dans un état non valide.
Ceci est communément appelé «échec précoce» ou «échec rapide» .
la source
Cela signifie que vous détectez le problème immédiatement et de manière fiable .
Considérer:
.NET améliore cela en séparant
NullReferenceException
("vous avez déréférencé une valeur nulle") deArgumentNullException
("vous n'auriez pas dû passer null comme argument - et c'était pour ce paramètre). J'aimerais que Java fasse la même chose, mais même avec juste unNullPointerException
, il est encore plus facile de corriger le code si l'erreur est lancée au plus tôt à laquelle elle peut être détectée.la source
Utiliser
requireNonNull()
comme premières instructions dans une méthode permet d'identifier immédiatement / rapidement la cause de l'exception.Le stacktrace indique clairement que l'exception a été levée dès l'entrée de la méthode car l'appelant n'a pas respecté les exigences / contrat. Passer un
null
objet à une autre méthode peut en effet provoquer une exception à la fois mais la cause du problème peut être plus compliquée à comprendre car l'exception sera lancée dans une invocation spécifique sur l'null
objet qui peut être beaucoup plus loin.Voici un exemple concret et réel qui montre pourquoi nous devons favoriser l'échec rapide en général et plus particulièrement en utilisant
Object.requireNonNull()
ou de toute manière pour effectuer une vérification non nulle sur des paramètres conçus pour ne pas l'êtrenull
.Supposons une
Dictionary
classe qui compose unLookupService
et unList
deString
représenter les mots contenus dans. Ces champs sont conçus pour ne pas l'êtrenull
et l'un d'eux est passé dans leDictionary
constructeur.Supposons maintenant une "mauvaise" implémentation de
Dictionary
sansnull
vérification dans l'entrée de méthode (ici c'est le constructeur):Maintenant, appelons le
Dictionary
constructeur avec unenull
référence pour lewords
paramètre:La JVM jette le NPE à cette déclaration:
L'exception est déclenchée dans la
LookupService
classe alors que son origine est bien antérieure (leDictionary
constructeur). Cela rend l'analyse globale des problèmes beaucoup moins évidente.Est-ce
words
null
? Est-cewords.get(0) null
? Tous les deux ? Pourquoi l'un, l'autre ou peut-être les deuxnull
? S'agit-il d'une erreur de codage dansDictionary
(constructeur? Méthode invoquée?)? S'agit-il d'une erreur de codage qui n'était pas un service local mais un service distant ou une bibliothèque tierce avec peu d'informations de débogage ou imaginez que vous n'aviez pas 2 couches mais 4 ou 5 couches d'appels d'objets avant celaLookupService
? (constructeur? méthode invoquée?)?Enfin, nous devrons inspecter plus de code pour trouver l'origine de l'erreur et dans une classe plus complexe, peut-être même utiliser un débogueur pour comprendre plus facilement ce qui s'est passé.
Mais pourquoi une chose simple (un manque de contrôle nul) devient un problème complexe?
Parce que nous avons autorisé le bug / manque initial identifiable sur une fuite de composant spécifique sur les composants inférieurs.
Imaginez que ce être détectées? Le problème serait encore plus complexe à analyser.
LookupService
null
La façon de favoriser est donc:
De cette façon, pas de maux de tête: nous obtenons l'exception levée dès qu'elle est reçue:
Notez qu'ici j'ai illustré le problème avec un constructeur mais un appel de méthode pourrait avoir la même contrainte de vérification non nulle.
la source
En remarque, cet échec rapide avant a
Object#requireNotNull
été implémenté légèrement différent avant java-9 dans certaines des classes jre elles-mêmes. Supposons que le cas:Dans java-8, cela se compile comme (uniquement les parties pertinentes)
Fondamentalement, une opération comme:
yourReference.getClass
- qui échouerait si votre référence estnull
.Les choses ont changé dans jdk-9 où le même code compile que
Ou en gros
Objects.requireNotNull (yourReference)
la source
L'utilisation de base consiste à vérifier et à lancer
NullPointerException
immédiatement.Une meilleure alternative (raccourci) pour répondre à la même exigence est l' annotation @NonNull par lombok.
la source
Une exception de pointeur nul est levée lorsque vous accédez à un membre d'un objet qui se trouve
null
à un stade ultérieur.Objects.requireNonNull()
vérifie immédiatement la valeur et lève l'exception instantanément sans avancer.la source
Je pense qu'il devrait être utilisé dans les constructeurs de copie et dans d'autres cas comme DI dont le paramètre d'entrée est un objet, vous devriez vérifier si le paramètre est nul. Dans de telles circonstances, vous pouvez facilement utiliser cette méthode statique.
la source
Dans le contexte des extensions du compilateur qui implémentent la vérification de la nullité (par exemple: uber / NullAway ),
Objects.requireNonNull
devrait être utilisé avec parcimonie dans les cas où vous avez un champ nullable que vous savez par hasard n'est pas nul à un certain point de votre code.De cette façon, il existe deux usages principaux:
Validation
Marquage de nullité (passage de @Nullable à @Nonnull)
Exemple d'utilisation du marquage Nullability:
la source
En plus de toutes les bonnes réponses:
Nous l'utilisons dans des flux réactifs. Habituellement, le résultat
NullpointerException
s sont enveloppés dans d'autres exceptions en fonction de leur occurrence dans le flux. Par conséquent, nous pouvons plus tard décider facilement comment gérer l'erreur.Juste un exemple: imaginez que vous avez
où
parseAndValidate
enveloppe leNullPointerException
derequireNonNull
dans unParsingException
.Vous pouvez maintenant décider, par exemple, quand réessayer ou non:
Sans la vérification, l'exception NullPointerException se produira dans la
save
méthode, ce qui entraînera des tentatives sans fin. Même en valeur, imaginez un abonnement longue durée, ajoutantMaintenant,
RetryExhaustException
cela tuera votre abonnement.la source