Personne n'aime NullPointerException ! Existe-t-il un moyen de les éviter ? Peut être. .
Cet article abordera les technologies suivantes
1.Type facultatif (récemment introduit dans Java 8)
2.Classe Objects (originale en Java 7)
Classe facultative en Java 8
qu'est-ce que c'est?
1. Nouveaux types introduits dans Java 8
2. Il est utilisé comme wrapper pour un objet d'un type spécifié ou pour des scénarios dans lesquels aucun objet (null) n'existe.
En termes simples, c'est une meilleure alternative pour gérer les valeurs nulles (attention : cela n'est peut-être pas si évident à première vue)
Utilisation de base
C'est un type (une classe) - alors comment créer une instance de ce type ?
Utilisez simplement ses trois méthodes statiques :
Copiez le code comme suit :
public static Facultatif<String> stringOptional(String input) {
return Facultatif.of(input);
}
Simple et clair : créez un wrapper facultatif contenant cette valeur. N'oubliez pas que si cette valeur est nulle, NPE sera lancé !
Copiez le code comme suit :
public static Facultatif<String> stringNullableOptional(String input) {
if (!new Random().nextBoolean()) {
entrée = nul ;
}
return Facultatif.ofNullable(input);
}
Personnellement, je pense que c'est mieux. De cette façon, il n'y aura aucun risque de NPE - si l'entrée est nulle, un facultatif vide sera renvoyé.
Copiez le code comme suit :
public static Facultatif<String> videOptional() {
return Facultatif.empty();
}
Si vous voulez vraiment simplement renvoyer une valeur "nulle". Une valeur « vide » ne signifie pas null.
D'accord, alors comment consommer/utiliser Facultatif ?
Copiez le code comme suit :
public static void consumerOptional() {
Facultatif<String> enveloppé = Facultatif.of("aString");
si (wrapped.isPresent()) {
System.out.println("Chaîne obtenue - " + enveloppé.get());
}
autre {
System.out.println("Je t'ai eu !");
}
}
Le moyen simple consiste à vérifier si le wrapper facultatif a réellement une valeur (en utilisant la méthode isPresent) - vous vous demanderez quel avantage cela présente par rapport à l'utilisation de if(myObj != null). Ne vous inquiétez pas, je vais vous expliquer cela clairement.
Copiez le code comme suit :
public static void consumerNullableOptional() {
Entrée de chaîne = null ;
if (new Random().nextBoolean()) {
entrée = "iCanBeNull" ;
}
Facultatif<String> enveloppé = Facultatif.ofNullable(input);
System.out.println(wrapped.orElse("default"));
}
Vous pouvez utiliser la méthode orElse, de sorte que si la valeur encapsulée est effectivement une valeur nulle, vous puissiez l'utiliser pour renvoyer une valeur par défaut - ses avantages sont évidents. Lors de l’extraction de la valeur réelle, vous pouvez éviter la méthode évidemment redondante consistant à appeler la méthode ifPresent.
Copiez le code comme suit :
public static void consumerEmptyOptional() {
Entrée de chaîne = null ;
if (new Random().nextBoolean()) {
entrée = "iCanBeNull" ;
}
Facultatif<String> enveloppé = Facultatif.ofNullable(input);
System.out.println(wrapped.orElseGet(
() -> {
renvoyer "defaultBySupplier" ;
}
));
}
Je suis un peu confus à ce sujet. Pourquoi existe-t-il deux méthodes différentes pour le même objectif ? orElse et orElseGet peuvent évidemment être surchargés (avec le même nom mais des paramètres différents).
Quoi qu'il en soit, la différence évidente entre ces deux méthodes réside dans leurs paramètres - vous pouvez choisir d'utiliser des expressions lambda au lieu d'instances de Supplier pour y parvenir (une interface fonctionnelle)
Pourquoi l'utilisation de Facultatif est-elle meilleure que la vérification nulle courante ?
1. Le plus grand avantage de l'utilisation de Facultatif est que vous pouvez exprimer votre intention plus clairement - le retour d'une valeur nulle rendra les consommateurs confus (lorsque NPE se produit) si cela est renvoyé intentionnellement, vous devez donc vérifier la position javadoc pour plus de détails. . L’utilisation de Facultatif est assez simple.
2. AvecOptional, vous pouvez complètement éviter le NPE - comme mentionné ci-dessus, l'utilisation deOptional.ofNullable, orElse et orElseGet peut nous éloigner du NPE.
Encore un sauveur !
Jetez un œil à cet extrait de code et copiez le code ci-dessous :
package com.abhirockzz.wordpress.npesaviors;
importer java.util.Map ;
importer java.util.Objects ;
classe publique UsingObjects {
String getVal(Map<String, String> aMap, clé de chaîne) {
return aMap.containsKey(key) ? aMap.get(key) : null;
}
public static void main (String[] arguments) {
UsingObjects obj = new UsingObjects();
obj.getVal(null, "factice");
}
}
Lequel pourrait être vide ?
1.Objet cartographique
2. Clé utilisée pour la recherche
3. Cette instance d'appel de méthode
Si NPE est lancé, comment pouvons-nous déterminer lequel est nul ?
Copiez le code comme suit :
package com.abhirockzz.wordpress.npesaviors;
importer java.util.Map ;
importer java.util.Objects ;
classe publique UsingObjects {
String getValSafe(Map<String, String> aMap, clé de chaîne) {
Map<String, String> safeMap = Objects.requireNonNull(aMap,
"La carte est nulle");
String safeKey = Objects.requireNonNull(key, "La clé est nulle");
return safeMap.containsKey(safeKey) ? safeMap.get(safeKey) : null;
}
public static void main (String[] arguments) {
UsingObjects obj = new UsingObjects();
obj.getValSafe(null, "factice");
}
}
Méthode requireNonNull
1. Si l'objet n'est pas nul, retournez-le
2. Si la valeur est nulle, le NPE renvoyé aura le message spécifié.
Pourquoi est-ce mieux que if(myObj!=null) ?
La trace de pile que vous voyez verra clairement l'appel de la méthode Objects.requireNonNull. Ceci, combiné à votre propre journal d’erreurs, peut vous permettre de localiser le problème plus rapidement. . . Au moins, c'est plus rapide à mon avis.
Vous pouvez également personnaliser votre propre validateur, par exemple en implémentant un validateur simple pour garantir qu'il n'y a pas de valeurs nulles.
Copiez le code comme suit :
importer java.util.Collections ;
importer java.util.List ;
importer java.util.Objects ;
importer java.util.function.Predicate ;
classe publique RandomGist {
public static <T> T requireNonEmpty (objet T, prédicat Predicate <T>, String msgToCaller) {
Objets.requireNonNull(objet);
Objects.requireNonNull(prédicat);
if (predicate.test(object)){
lancer une nouvelle IllegalArgumentException (msgToCaller);
}
renvoyer l'objet ;
}
public static void main (String[] arguments) {
//Utilisation 1 : une chaîne vide (intentionnelle)
Chaîne s = "" ;
System.out.println(requireNonEmpty(Objects.requireNonNull(s), (s1) -> s1.isEmpty() , "Ma chaîne est vide!"));
//Utilisation 2 : une liste vide (intentionnelle)
Liste liste = Collections.emptyList();
System.out.println(requireNonEmpty(Objects.requireNonNull(list), (l) -> l.isEmpty(), "La liste est vide!").size());
//Usage 3 : un utilisateur vide (intentionnel)
Utilisateur utilisateur = nouvel utilisateur("");
System.out.println(requireNonEmpty(Objects.requireNonNull(user), (u) -> u.getName().isEmpty(), "L'utilisateur est vide !"));
}
classe statique privée Utilisateur {
nom de chaîne privé ;
Utilisateur public (nom de chaîne) {
this.name = nom ;
}
chaîne publique getName(){
renvoyer le nom ;
}
}
}
Ne laissez pas les NPE devenir pénibles au mauvais endroit. Nous disposons de nombreux outils pour mieux lutter contre les NPE et même les éradiquer complètement !