Voir le flux RSS

Gugelhupf

[Actualité] [Java] Utilisation d'Optional<T> pour éviter d'utiliser explicitement null

Noter ce billet
par , 01/05/2017 à 20h45 (1374 Affichages)
La classe Optional<T>, apparue avec Java 8, sert de syntaxe alternative à une utilisation explicite du mot-clé null. En effet, l’utilisation du mot-clé null est souvent contestée, car elle n’apporte pas forcément une bonne lisibilité à la lecture du code.

Voici un exemple d'utilisation d'Optional :
Exemple sans Optional Exemple avec Optional
Code Java : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
if (myObject != null) {
    myObject.myMethod();
}
Code Java : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
if (myObjectOptional.isPresent()) {
    myObjectOptional.get().myMethod();
}
Nous utilisons Optional pour vérifier la présence d'un élément facultatif (d'un élément qui peut ne pas exister) avant de l'utiliser.

Mais qu'est-ce qu'un Optional ? Vous l'avez surement déjà vu avec l'utilisation des Stream introduit dans Java 8, Optional n'est ni plus ni moins un petit utilitaire qui fait office de container, c'est un objet qui contient votre instance.

Voici quelques exemples de création d'Optional<T> :
Exemple Description
Code Java : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
public Optional<String> method(){
    String returnValue = null;
    // Code
    return Optional.ofNullable(returnValue);
}
returnValue peut être null
Code Java : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
public Optional<String> method(){
    String returnValue = null;
    // Code
    return Optional.of(returnValue);
}
un NullPointerException sera lancé si returnValue vaut null.
Code Java : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
public Optional<String> method(){
    return Optional.empty();
}
Pour instancier un Optional<T> vide


La classe Optional<T> est à utiliser avec les retours de méthode, d’après Brian Goetz, créateur de cette classe (source) :
you probably should never use it for something that returns an array of results, or a list of results; instead return an empty array or list. You should almost never use it as a field of something or a method parameter.
N'utilisez pas optional sur votre retour de méthode si c'est un container (un tableau, une List ou Map), retournez un container vide.
N'utilisez pas optional pour vos attributs
N'utilisez pas optional pour vos paramètres de méthode

Chaque feature introduit dans un langage pousse généralement le développeur à l'utiliser un maximum, le risque est bien sûr d'en abuser. D'où la raison qui pousse Brian Goetz à indiquer qu'il ne faut pas utiliser Optional partout.

À noter aussi que si vous rencontrez un tel code :
Code Java : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
if (myOptional != null) {
    if (myOptional.isPresent()) {
        // Code
    }
}
... c'est que la personne l'ayant codé n'a rien compris à l'utilisation d'Optional.

Envoyer le billet « [Java] Utilisation d'Optional<T> pour éviter d'utiliser explicitement null » dans le blog Viadeo Envoyer le billet « [Java] Utilisation d'Optional<T> pour éviter d'utiliser explicitement null » dans le blog Twitter Envoyer le billet « [Java] Utilisation d'Optional<T> pour éviter d'utiliser explicitement null » dans le blog Google Envoyer le billet « [Java] Utilisation d'Optional<T> pour éviter d'utiliser explicitement null » dans le blog Facebook Envoyer le billet « [Java] Utilisation d'Optional<T> pour éviter d'utiliser explicitement null » dans le blog Digg Envoyer le billet « [Java] Utilisation d'Optional<T> pour éviter d'utiliser explicitement null » dans le blog Delicious Envoyer le billet « [Java] Utilisation d'Optional<T> pour éviter d'utiliser explicitement null » dans le blog MySpace Envoyer le billet « [Java] Utilisation d'Optional<T> pour éviter d'utiliser explicitement null » dans le blog Yahoo

Mis à jour 08/05/2017 à 09h25 par ClaudeLELOUP

Catégories
Java , Programmation

Commentaires

  1. Avatar de avdyk
    • |
    • permalink
    Bonjour,

    Utiliser isPresent() à la place de la comparaison du null n'apporte pas grand chose, ni en terme d'efficacité, ni en terme de clarté. Il est plus intéressant de profiter des méthodes d'Optional pour effectuer les opérations si l'Optional contient une valeur:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    final String test = " hello "; // essayer avec d'autres valeurs et null
    Optional.ofNullable(test)
                    .map(String::trim)
                    .filter(s -> s.length() > 0)
                    .ifPresent(System.out::println);
    Si on veut fournir une valeur par défaut:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    String test = " hello "; // essayer avec d'autres valeurs et null
    final String withDefault = Optional.ofNullable(test)
                    .map(String::trim)
                    .filter(s -> s.length() > 0)
                    .orElse("Valeur par défaut");
    Tester si un Optional n'est pas null ne signifie pas qu'on a rien compris car un Optional pourrait être null. L'évolution des habitudes de programmation en Java veut qu'on ne teste plus si une collection, un tableau ou un Optional est null car c'est une mauvaise habitude de fournir une instance nulle. Il est recommandé de retourner Optional.empty(), une collection ou un tableau vide.

    Dans le cas d'un Optional, le null serait plutôt un bug et l'utilisateur de l'application ne pourrait rien y faire.
  2. Avatar de Gugelhupf
    • |
    • permalink
    Bonjour @avdyk,

    Merci pour ton retour, en ce qui concerne la clarté, la documentation Oracle dit (source) :
    its purpose is to help design more-comprehensible APIs so that by just reading the signature of a method, you can tell whether you can expect an optional value. This forces you to actively unwrap an Optional to deal with the absence of a value.
    Pour ce qui est de l'efficacité (performances ?), je n'ai pas testé, mais il semblerait que le fait de wrapper/unwrapper avec Optional n'impacte pas sur les performances.

    Optional est un objet comme un autre, mais si un Optional est null au lieu d'être vide, la feature perd son intérêt.

    P.-S. : Une petite syntaxe stream pour le coalesce en Java 8 : String a = Stream.of( null, null, "valeur defaut").filter( Objects::nonNull ).findFirst().get();