En Java, gérer les valeurs nulles peut être un véritable casse-tête. Les valeurs nulles peuvent causer toutes sortes de problèmes dans votre code, de NullPointerExceptions
alambiqué if
déclarations et une logique sujette aux erreurs. Heureusement, Java 8 a introduit le Optional
class, qui offre un moyen simple et puissant de gérer les valeurs nulles et d’améliorer la qualité du code. Optional
est un objet conteneur qui peut ou non contenir une valeur non nulle et fournit une gamme de méthodes pratiques pour travailler avec son contenu. Dans cet article, nous allons explorer les nombreux cas d’utilisation de Optional
en Java et vous montrer comment utiliser cette classe puissante pour écrire du code plus propre, plus expressif et plus résilient.
Plongeons donc dans quelques exemples d’utilisations de Optional
s.
Éviter les exceptions NullPointer
L’un des cas d’utilisation les plus courants de Optional
est d’éviter NullPointerExceptions
. En enveloppant un potentiel null
valeur dans un Optional
vous pouvez accéder en toute sécurité à la valeur sans risquer NullPointerException
. Par exemple, si vous avez une méthode qui renvoie une valeur qui pourrait être null
vous pouvez retourner un Optional
à la place, puis utilisez Optional
méthodes pour accéder à la valeur en toute sécurité.
String value = null;
Optional<String> optionalValue = Optional.ofNullable(value);
if (optionalValue.isPresent()) {
System.out.println(optionalValue.get());
}
Dans cet exemple, nous avons créé un Optional
à partir d’une valeur potentiellement nulle. On utilise alors le Optional.isPresent()
méthode pour vérifier si la valeur est présente, et utilisez Optional.get()
pour accéder à la valeur en toute sécurité.
Simplification de la gestion des exceptions
Un autre cas d’utilisation convaincant de Optional
est de simplifier la gestion des exceptions. Vous pouvez utiliser le Optional.orElseThrow()
méthode pour lever une exception si la valeur n’est pas présente. Cela peut rendre votre code plus concis et plus facile à lire, en particulier lors de la gestion de plusieurs exceptions potentielles. Par exemple:
Optional<String> optionalValue = Optional.empty();
String value = optionalValue.orElseThrow(() -> new RuntimeException("Value is not present!"));
Dans cet exemple, nous créons un vide Optional
et utilise Optional.orElseThrow()
jeter un RuntimeException
si la valeur n’est pas présente. Cela simplifie le code de gestion des exceptions et le rend plus concis et lisible.
Retarder la gestion des erreurs à l’appelant
Un Optional
en Java est également très utile pour retarder la décision de ce qui doit se passer en cas de problème dans un contexte supérieur. Au lieu que la fonction décide du comportement (tuer le thread ou utiliser une valeur par défaut), l’appelant peut maintenant décider ce qui est le mieux dans le contexte de l’appelant. Supposons que nous ayons une méthode qui recherche un livre dans une bibliothèque en fonction de l’ISBN du livre :
public static Book searchBook(String isbn) {
Library library = Library.getInstance();
Book book = library.searchByISBN(isbn);
if (book != null) {
return book;
} else {
throw new IllegalArgumentException("Book with ISBN " + isbn + " not found in the library");
}
}
Cette méthode lève une exception si le livre avec l’ISBN donné n’est pas trouvé dans la bibliothèque. La décision sur la façon de gérer cette erreur est prise par la méthode elle-même. Maintenant, modifions cette méthode pour utiliser Optional
pour retarder la gestion des erreurs à l’appelant :
public static Optional<Book> searchBook(String isbn) {
Library library = Library.getInstance();
Book book = library.searchByISBN(isbn);
if (book != null) {
return Optional.of(book);
} else {
return Optional.empty();
}
}
Dans cette version modifiée, si le livre avec l’ISBN donné n’est pas trouvé dans la bibliothèque, la méthode retourne un vide Optional
, indiquant qu’une erreur s’est produite. Sinon, il renvoie un Optional
contenant le livre.
Maintenant, l’appelant de cette méthode peut décider comment gérer l’erreur. Voici un exemple :
Optional<Book> book = searchBook("9780132350884");
if (book.isPresent()) {
System.out.println("Book title: " + book.get().getTitle());
} else {
System.out.println("Error: book not found");
}
Dans cet exemple, l’appelant affichera un message d’erreur si le livre avec l’ISBN donné n’est pas trouvé dans la bibliothèque. Sinon, il imprimera le titre du livre. L’appelant décide maintenant comment gérer l’erreur, pas la méthode elle-même.
Merci à mon ami pour ce partage.
Chaîner des valeurs facultatives
On peut aussi enchaîner Optional
valeurs à l’aide de Optional.flatMap()
méthode. Cela peut être utile pour accéder à des valeurs imbriquées dans d’autres objets. Par exemple, si vous avez un objet qui contient un autre objet qui pourrait être nul, vous pouvez utiliser Optional.flatMap()
pour accéder à la valeur imbriquée sans risquer un NullPointerException
.
Optional<Author> optionalAuthor = Optional.ofNullable(book)
.flatMap(Book::getAuthor);
Dans cet exemple, nous enchaînons deux Optional
valeurs utilisant Optional.flatMap()
. Nous créons un Optional
à partir d’un objet livre potentiellement nul, puis utilisez Optional.flatMap()
pour accéder à la valeur author si elle est présente. Cela simplifie le code et évite le besoin de vérifications nulles.
Définition des valeurs par défaut
Optional
peut également être utilisé pour définir des valeurs par défaut pour les valeurs manquantes ou nulles. Vous pouvez utiliser Optional.orElse()
pour spécifier une valeur par défaut à renvoyer si le Optional
est vide. Cela peut rendre votre code plus résilient et réduire la probabilité d’erreurs causées par des valeurs nulles ou manquantes.
String value = null;
String defaultValue = "default";
String result = Optional.ofNullable(value)
.orElse(defaultValue);
Dans cet exemple, nous avons créé un Optional
à partir d’une valeur potentiellement nulle, et utilisé Optional.orElse()
pour spécifier une valeur par défaut si le Optional
est vide. Cela rend le code plus résilient et évite les erreurs causées par des valeurs nulles ou manquantes.
Éviter le code standard
En utilisant Optional
vous pouvez éviter d’écrire du code passe-partout pour vérifier les valeurs nulles. Optional
fournit une manière concise et expressive de gérer null
valeurs, ce qui peut rendre votre code plus lisible et maintenable. Par exemple, vous pouvez utiliser Optional.map()
effectuer une transformation sur une valeur uniquement si elle est présente, sans avoir à écrire un if
déclaration à vérifier null
. Par exemple:
String value = null;
Optional<String> optionalValue = Optional.ofNullable(value);
String result = optionalValue.map(s -> s.toUpperCase())
.orElse("default");
Dans cet exemple, nous créons un Optional
à partir d’une valeur potentiellement nulle, et utilisez Optional.map()
pour effectuer une transformation sur la valeur uniquement si elle est présente. Cela évite d’avoir besoin d’un if
déclaration à vérifier null
et rend le code plus concis et lisible.
Faciliter la composition de la méthode
Optional
peut être utilisé pour composer ensemble des méthodes de manière plus concise et expressive. En enveloppant la valeur de retour d’une méthode dans un Optional
vous pouvez utiliser Optional
méthodes pour enchaîner plusieurs appels de méthodes. Cela peut rendre votre code plus lisible et plus facile à comprendre. Par exemple:
Optional<String> optionalValue = Optional.of("Hello")
.map(s -> s.toUpperCase())
.filter(s -> s.startsWith("H"));
Dans cet exemple, nous créons un Optional
à partir d’une chaîne, utilisez Optional.map()
pour le convertir en majuscule, puis utilisez Optional.filter()
pour supprimer toutes les valeurs qui ne commencent pas par "H"
. Cela nous permet de composer plusieurs appels de méthodes ensemble dans une seule expression.
Gestion des collections facultatives
Optional
peut être utilisé pour gérer des collections de Optional
valeurs de manière plus concise et lisible. Par exemple, si vous avez une collection de Optional
valeurs, vous pouvez utiliser Optional.stream()
pour créer un flux de valeurs non vides, puis utilisez stream
méthodes pour effectuer des opérations sur les valeurs. Cela peut rendre votre code plus expressif et plus facile à comprendre. Par exemple:
List<Optional<String>> optionalList = Arrays.asList(Optional.empty(),
Optional.of("Bazlur"),
Optional.of("Rahman"));
String result = optionalList.stream()
.flatMap(Optional::stream)
.collect(Collectors.joining(" "));
Dans cet exemple, nous créons une liste de Optional
valeurs, utiliser Optional.stream()
pour créer un flux de valeurs non vides, puis utilisez stream
méthodes pour joindre les valeurs non vides en une seule chaîne. Cela nous permet de gérer des collections de Optional
valeurs avec plus d’élégance et d’expression.
Simplifier les configurations
Optional
peut simplifier la gestion de la configuration en fournissant une valeur par défaut pour un paramètre de configuration. Par exemple, si vous avez un paramètre de configuration manquant, vous pouvez utiliser Optional
pour fournir une valeur par défaut si le paramètre n’est pas présent. Cela peut rendre votre code plus résilient et plus facile à maintenir. Par exemple:
String value = Optional.ofNullable(System.getProperty("my.property"))
.orElse("default");
Dans cet exemple, nous créons un Optional
à partir d’une valeur de propriété système et d’une utilisation Optional.orElse()
pour spécifier une valeur par défaut si la propriété n’est pas présente. Cela rend la configuration plus résiliente et évite les erreurs causées par des paramètres de configuration manquants.
Simplification des signatures de méthode
Optional
peut simplifier la gestion de la configuration en fournissant une valeur par défaut pour un paramètre de configuration. Par exemple, si vous avez un paramètre de configuration manquant, vous pouvez utiliser Optional
pour fournir une valeur par défaut si le paramètre n’est pas présent. Cela peut rendre votre code plus résilient et plus facile à maintenir. Par exemple: