Il est très courant de trouver dans le code de nos applications les lignes suivantes :
if (maVariable == null) {}
ou alors :
if (maVariable !=null) {}
ou encore :
if (maMethode() == null){}
ou bien :
…
return null;
}
Je suis sur que vous l’aurez constaté, l’ensemble de ces portions de code ont un point commun : la référence null.
Si l’on comprend bien techniquement ce que l’on est en train de faire, fonctionnellement des fois on peut se poser la question.
Dans chacun des cas, on vérifie si l’objet que l’on va manipuler ne contient pas une référence nulle, ceci afin d’éviter la célèbre NullPointerException.
Le fait de se retrouver avec un objet qui contient une référence nulle peut être souhaité, c’est à dire que le fait d’affecter null à une instance indique qu’une référence attendue n’a pas été trouvée (par exemple).
Dans ce cas là, on indique dans la javadoc de la méthode que ce comportement est possible et qu’il faut faire attention. Implicitement, cela veut dire que l’objet retourné par la méthode est optionnel.
Personnellement, je n’aime pas beaucoup écrire ce type de code je ne trouve pas ça très expressif et très joli.
Pour adresser ce problème, l’API Guava a introduit un type nommé Optional (depuis la version 10 de l’API)
L’idée de ce nouveau type est d’encapsuler la référence afin de transformer la question :
Est ce que la référence est null ?
par
Est ce que la référence est présente ou absente ?
Au premier abord, on peut dire que la question a le même sens, dit de deux façons différentes.
La vraie différence se trouve dans le code. Je vais essayer de vous faire un tour d’horizon.
Comme je vous le disais plus tôt, l’objectif du type Optional est de contenir une référence typée. La classe Optional est paramétrée.
Pour mieux comprendre son fonctionnement, rien de mieux qu’un petit exemple, soit la méthode suivante écrite de manière traditionnelle :
public String getPersonName(final Person person){
if(person != null){
return person.getName();
}
return null;
}
…
final Person person = new Person(“Fabrice”);
String name = getPersonName(person);
if(name != null) {
System.out.println(“nom de la personne “ + name);
}else {
System.out.println(“nom de la personne : inconnu”);
}
Voila comment elle pourrait être refactorée à l’aide de la classe Optional<T> :
public Optional<String> getPersonName(final Person person){
if(person != null){
return Optional.fromNullable(person.getName());
}
return Optional.absent();
}
…
final Person person = new Person(“Fabrice”);
System.out.println(“nom de la person “ + getPersonName(person).or(“inconnu”));
L’exemple présenté ci-dessus est un peu naif mais sans forcément connaitre l’API de cette classe, on peut voir tout de suite l’intérêt du type Optional.
Il existe 3 façons de créer une instance d’Optional :
– Optional.fromNullable() : création à partir d’une référence potentiellement nulle. Cette instance répondra aux méthodes : isPresent() ou isAbsent()
– Optional.absent() : création d’un optional contenant une référence nulle
– Optional.of() : création à partir d’une référence qui ne peut pas être nulle.
Plusieurs méthodes sont disponibles pour interagir avec un Optional :
– Optional.or() : permet, en cas de référence absente, de fournir une valeur par défaut.
– Optional.get() : permet d’obtenir concrètement la référence.
– Optional.orNull() : permet de récupérer une référence null si la référence encapsulée est absente.
– Optional.isPresent() : remplace le traditionnel : if(maVariable != null){..}
En utilisant Optional, on peut fournir un code plus ‘self’ expressif, plus maitrisé et sûr. En suivant le lien de l’article, vous pourrez découvrir l’ensemble des possibilités offertes par cette classe.
Aussi, il me semble qu’un type équivalent serait disponible dans la prochaine version du JDK. Malheureusement, je n’ai pas retrouvé le lien permettant d’appuyer ce propos.
A partir de maintenant, toutes les options sont permises 😉
#java #guava #optional #null