Utiliser Optional
pour la sécurité vis - à - vis des valeurs null
Dans cette étape, nous allons explorer une approche plus moderne pour gérer les valeurs null
potentielles en Java en utilisant la classe Optional
, introduite en Java 8. Optional
est un objet conteneur qui peut ou non contenir une valeur non nulle. Il offre un moyen de représenter de manière plus explicite la présence ou l'absence d'une valeur, ce qui peut aider à réduire le risque de NullPointerException
.
Bien que les vérifications if (collection != null)
soient parfaitement valides et nécessaires dans de nombreuses situations, Optional
peut rendre votre code plus lisible et expressif, en particulier lorsqu'il s'agit de méthodes qui peuvent retourner une valeur ou null
.
Voyons comment nous pouvons utiliser Optional
avec une collection. Bien que Optional
soit généralement utilisé pour des valeurs uniques, vous pourriez rencontrer des scénarios où une méthode retourne un Optional<List<SomeObject>>
.
-
Ouvrez le fichier HelloJava.java
dans l'éditeur WebIDE.
-
Remplacez le contenu par le code suivant qui montre comment utiliser Optional
avec une liste potentiellement nulle :
import java.util.List;
import java.util.ArrayList;
import java.util.Optional; // Import Optional
public class HelloJava {
// Une méthode qui peut retourner un Optional contenant une liste, ou un Optional vide
public static Optional<List<String>> getNames(boolean includeNames) {
if (includeNames) {
List<String> names = new ArrayList<>();
names.add("Alice");
names.add("Bob");
return Optional.of(names); // Retourne un Optional contenant la liste
} else {
return Optional.empty(); // Retourne un Optional vide
}
}
public static void main(String[] args) {
// Cas 1 : Obtenir les noms lorsque includeNames est true
Optional<List<String>> namesOptional1 = getNames(true);
System.out.println("Checking namesOptional1:");
// Vérifie si l'Optional contient une valeur
if (namesOptional1.isPresent()) {
List<String> names = namesOptional1.get(); // Récupère la liste de l'Optional
System.out.println("List is present. Size: " + names.size());
// Vous pouvez également vérifier si la liste elle - même est vide
if (names.isEmpty()) {
System.out.println("List is empty.");
} else {
System.out.println("List is not empty. First name: " + names.get(0));
}
} else {
System.out.println("List is not present (Optional is empty).");
}
System.out.println("---");
// Cas 2 : Obtenir les noms lorsque includeNames est false
Optional<List<String>> namesOptional2 = getNames(false);
System.out.println("Checking namesOptional2:");
if (namesOptional2.isPresent()) {
List<String> names = namesOptional2.get();
System.out.println("List is present. Size: " + names.size());
if (names.isEmpty()) {
System.out.println("List is empty.");
} else {
System.out.println("List is not empty. First name: " + names.get(0));
}
} else {
System.out.println("List is not present (Optional is empty).");
}
System.out.println("\nProgram finished.");
}
}
Dans ce code :
- Nous définissons une méthode
getNames
qui retourne un Optional<List<String>>
. Cette méthode simule un scénario où vous pouvez obtenir une liste ou rien du tout (représenté par un Optional
vide).
- Dans la méthode
main
, nous appelons getNames
avec true
et false
pour tester les deux cas.
- Nous utilisons
namesOptional.isPresent()
pour vérifier si l'Optional
contient une liste.
- Si
isPresent()
est vrai, nous utilisons namesOptional.get()
pour récupérer la liste. Cela est sûr car nous avons déjà vérifié la présence.
- À l'intérieur du bloc
isPresent()
, nous pouvons ensuite effectuer des vérifications sur la liste elle - même, comme names.isEmpty()
.
-
Enregistrez le fichier.
-
Compilez le programme dans le Terminal :
javac HelloJava.java
-
Exécutez le programme :
java HelloJava
Vous devriez voir une sortie similaire à celle - ci :
Checking namesOptional1:
List is present. Size: 2
List is not empty. First name: Alice
---
Checking namesOptional2:
List is not present (Optional is empty).
Program finished.
Cette sortie montre comment Optional
nous aide à gérer le cas où une liste peut ne pas être retournée du tout.
Optional
offre également d'autres méthodes utiles pour gérer l'absence d'une valeur, telles que :
orElse(defaultValue)
: Retourne la valeur si elle est présente, sinon retourne une valeur par défaut.
orElseGet(supplier)
: Retourne la valeur si elle est présente, sinon retourne le résultat de la fonction supplier
.
orElseThrow(exceptionSupplier)
: Retourne la valeur si elle est présente, sinon lance une exception produite par exceptionSupplier
.
ifPresent(consumer)
: Effectue l'action donnée si une valeur est présente.
Modifions le code pour utiliser ifPresent
d'une manière plus concise pour gérer la liste lorsqu'elle est présente.
-
Ouvrez HelloJava.java
dans l'éditeur.
-
Modifiez la méthode main
pour utiliser ifPresent
:
import java.util.List;
import java.util.ArrayList;
import java.util.Optional;
public class HelloJava {
public static Optional<List<String>> getNames(boolean includeNames) {
if (includeNames) {
List<String> names = new ArrayList<>();
names.add("Alice");
names.add("Bob");
return Optional.of(names);
} else {
return Optional.empty();
}
}
public static void main(String[] args) {
// Cas 1 : Obtenir les noms lorsque includeNames est true
Optional<List<String>> namesOptional1 = getNames(true);
System.out.println("Checking namesOptional1 using ifPresent:");
namesOptional1.ifPresent(names -> {
// Ce bloc ne s'exécute que si namesOptional1 contient une liste
System.out.println("List is present. Size: " + names.size());
if (names.isEmpty()) {
System.out.println("List is empty.");
} else {
System.out.println("List is not empty. First name: " + names.get(0));
}
});
if (!namesOptional1.isPresent()) { // Il faut toujours une vérification si vous devez gérer le cas d'absence
System.out.println("List is not present (Optional is empty).");
}
System.out.println("---");
// Cas 2 : Obtenir les noms lorsque includeNames est false
Optional<List<String>> namesOptional2 = getNames(false);
System.out.println("Checking namesOptional2 using ifPresent:");
namesOptional2.ifPresent(names -> {
System.out.println("List is present. Size: " + names.size());
if (names.isEmpty()) {
System.out.println("List is empty.");
} else {
System.out.println("List is not empty. First name: " + names.get(0));
}
});
if (!namesOptional2.isPresent()) {
System.out.println("List is not present (Optional is empty).");
}
System.out.println("\nProgram finished.");
}
}
Nous avons remplacé la structure if (namesOptional.isPresent()) { ... namesOptional.get() ... }
par namesOptional.ifPresent(names -> { ... })
. Le code à l'intérieur de l'expression lambda (names -> { ... }
) ne s'exécutera que si l'Optional
contient une valeur. Nous avons toujours ajouté une vérification if (!namesOptional.isPresent())
pour gérer le cas où l'Optional
est vide, car ifPresent
ne gère que le cas de présence.
-
Enregistrez le fichier.
-
Compilez le programme :
javac HelloJava.java
-
Exécutez le programme :
java HelloJava
La sortie devrait être la même que précédemment, démontrant que ifPresent
offre une autre façon de gérer la présence d'une valeur dans un Optional
.
L'utilisation de Optional
peut rendre l'intention de votre code plus claire en ce qui concerne la possibilité d'absence d'une valeur, et elle vous encourage à gérer explicitement cette absence, réduisant ainsi la probabilité de NullPointerException
inattendues.