Pourquoi devrait-on utiliser des Objets.requireNonNull()?
J'ai remarqué que beaucoup de Java 8 méthodes dans Oracle JDK utilisation Objects.requireNonNull()
, qui en interne jette NullPointerException
si l'objet donné (argument) est null
.
public static <T> T requireNonNull(T obj) {
if (obj == null)
throw new NullPointerException();
return obj;
}
Mais NullPointerException
seront jetés de toute façon si un null
objet est déréférencé. Alors, pourquoi doit-on faire cette null supplémentaires de vérifier et de les jeter
NullPointerException
?
Une réponse évidente (ou l'avantage), c'est qu'il rend le code plus lisible et je suis d'accord. Je suis désireux de connaître toutes les autres raisons pour l'utilisation
Objects.requireNonNull()
dans le début de la méthode.
Vous devez vous connecter pour publier un commentaire.
Parce que vous pouvez faire des choses explicite en le faisant. Comme:
Ou moins:
Maintenant, vous savoir:
new()
Comparez: vous créez un objet Foo aujourd'hui, et demain vous appelez une méthode qui utilise ce champ et le jette. Très probablement, vous ne saurez pas demain pourquoi cette référence est nulle hier quand il est passé au constructeur!
En d'autres termes: en utilisant explicitement cette méthode pour vérifier entrant des références que vous pouvez contrôle le point dans le temps lorsque l'exception est levée. Et la plupart du temps, vous voulez échouer aussi vite que possible!
Les principaux avantages sont:
bar
n'est pas nulle, et donc vous n'avez pas besoin de toutif (bar == null)
vérifie dans d'autres endroits!this.bar = Objects.requireNonNull(bar, "bar must not be null");
Objects.requireNonNull(bar, "bar must not be null");
. Merci pour celui-ci.com.google.common.base.Preconditions#checkNotNull(T)
qui, bien sûr, vous devez ajouter la goyave de la bibliothèque, mais pourquoi ne peuvent-ils suivre la goyave convention et de jeter unIllegalArgumentException
this.bar = Objects.requireNonNull(bar, "bar must not be null");
est ok 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/...Fail-fast
Le code devrait planter dès que possible. Il ne faut pas faire la moitié du travail, puis de déréférencement de la valeur null et crash puis en laissant la moitié de travailler causant le système soit dans un état non valide.
Ce qui est communément appelé "l'échec précoce" ou "fail-fast".
Cela signifie que vous détecter le problème immédiatement et de manière fiable.
Considérer:
.NET fait de mieux en séparant
NullReferenceException
("vous déréférencé une valeur "null") à partir deArgumentNullException
("vous ne devriez pas avoir passé dans la valeur null comme un argument - et c'est pour ce paramètre). Je souhaite que Java fait la même chose, mais même avec juste unNullPointerException
, c'est encore beaucoup plus facile de corriger le code si l'erreur est jetée sur le premier point à partir duquel il peut être détecté.À l'aide de
requireNonNull()
que les premières déclarations dans une méthode permettant d'identifier dès maintenant/rapide de la cause de l'exception.La stacktrace indique clairement que l'exception a été levée dès que l'entrée de la méthode parce que l'appelant n'a pas respecté les exigences/contrat.
Le passage d'un
null
objet à une autre méthode peut en effet provoquer une exception à un moment, mais la cause du problème peut être plus compliqué à comprendre que l'exception sera levée dans une invocation sur lenull
objet qui peut être beaucoup plus loin.Ici est un pas concret et réel exemple qui montre pourquoi nous avons à la faveur échouer rapidement, en général, et plus particulièrement à l'aide de
Object.requireNonNull()
ou de toute façon d'effectuer un pas de nulle vérifier les paramètres conçu pour être pasnull
.Supposons qu'un
Dictionary
classe qui compose unLookupService
et unList
deString
représentant les mots contenus dans. Ces champs sont conçus pour ne pas êtrenull
et l'un d'eux est passé dans leDictionary
constructeur.Supposons maintenant qu'un "mauvais" de la mise en œuvre de
Dictionary
sansnull
vérifier dans la méthode d'entrée (ici est le constructeur):Maintenant, nous allons appeler la
Dictionary
constructeur avec unnull
de référence pour lawords
paramètre :La JVM jette le NPE à cette déclaration :
L'exception est déclenchée dans le
LookupService
classe alors que l'origine est bien antérieure (laDictionary
constructeur). Il rend l'ensemble de l'analyse de la question beaucoup moins évidente.Est
words
null
? Estwords.get(0) null
? Les deux ?Pourquoi l'un, l'autre ou peut-être les deux sont
null
?Est-ce une erreur de codage dans
Dictionary
(constructeur? méthode invoquée?) ? Est-ce une erreur de codage dansLookupService
? (constructeur? méthode invoquée?) ?Enfin, nous aurons à inspecter plus de code pour trouver l'erreur d'origine et dans un complexe de classe 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 nulle vérifier) deviennent un problème complexe ?
Parce que nous ont permis de bug/ne pas identifiable sur un composant spécifique de la fuite sur une baisse des composants.
Imaginez que
LookupService
n'était pas un local de service, mais un service à distance ou d'un tiers de la bibliothèque avec quelques informations de débogage ou imaginez que vous n'avez pas 2 couches, mais 4 ou 5 couches de l'objet invocations avant que lenull
être détecté ? Le problème serait encore plus complexe à analyser.Ainsi, la manière de faveur est :
De cette façon, pas de maux de tête : nous obtenons l'exception levée dès que celui-ci est reçu :
Notez qu'ici, j'ai illustré le problème avec un constructeur mais un appel de méthode pourrait avoir le même non-nulle de vérification de la contrainte.
Comme une note de côté, ce échouer rapidement avant de
Object#requireNotNull
a été mis en œuvre légèrement différentes avant de java-9 à l'intérieur de certains de la jre classes elles-mêmes. Supposons le cas :Dans java 8 cette compile comme (seulement les parties pertinentes)
En gros, une opération comme :
yourReference.getClass
- ce qui serait un échec si yourRefercence estnull
.De choses ont changé dans le jdk-9, où le même code compile comme
Ou fondamentalement
Objects.requireNotNull (yourReference)
L'utilisation de base est de vérifier et de les jeter
NullPointerException
immédiatement.Une meilleure alternative (raccourci) pour répondre à la même exigence est @Non null annotation par lombok.