Blog

#AstuceDeCode 21 : lecture de properties d’objets sans if sur les cas null

Astuce de code
Share Button

Java 8 a amené les lambdas, qui simplifient grandement l’écriture de code car elles évitent la lourdeur des classes anonymes. Par ailleurs elles ont l’avantage de permettre plein de constructions sympa, notamment en ce qui concerne la lecture de properties d’objets quand ces derniers sont nullables. On va voir comment.

 

 

 

Débloque les + belles offres tech en 10 mins

Supposons qu’on ait une classe A, ayant une méthode getB(). Pour simplifier on va dire que l’API de la classe A est comme suit :


public class A {
   // ...

   public B getB() {
      ...
   }

   // ...
}

Maintenant voici un exemple avec la méthode foo qui à un moment lit une variable nullable de type A, et dont on veut récupérer sa propriété B. Jusqu’à présent quand le cas se présentait on avait quelque chose du genre :


A a = // ... ;
// ...
B b = null;
if (a != null) {
   b = a.getB();
}

Ce code présente tout de même les inconvénients suivants :

  • Au niveau de la méthode on ajoute un chemin dans le code, dû au if.
  • Cela implique également qu’il faut ajouter un cas de test pour ce if, ce qui peut vite devenir pénible à écrire.

Heureusement avec Java 8 et les lambdas il y a moyen de régler ce problème en une ligne. La première étape va consister à déclarer une interface fonctionnelle ValueGetter qui est la suivante :


@FunctionalInterface
public interface ValueGetter<S, T> {
   public T getValue(final S element);
}

Maintenant on va créer une méthode, ici dans une classe utilitaire qu’on va nommer MiscUtil, qui exploite cette interface. Voici le corps de cette méthode :


public static <S, T> T getValue(final S element, final ValueGetter<S, T> valueGetter) {
   Preconditions.checkNotNull(valueGetter, "valueGetter is null"); // Vous pouvez récupérer le Preconditions de Guava ou écrire le vôtre, c'est trivial.
   return element == null ? null: valueGetter.get(element);
}

Dès lors, pour revenir au code du début, on pourra remplacer le if par le code suivant :


A a = // ... ;
// ...
B b = MiscUtil.getValue(a, (e) -> e.getB());

Ici le cas peut paraître trivial mais quand vous avez des chaînes de properties ça peut être sympa à utiliser. De plus ici comme vous pouvez le voir vous n’avez plus qu’un chemin dans le code, ce qui le rend nettement plus simple à tester puisque vous n’avez plus besoin d’essayer toutes les combinaisons différentes de if que vous pourriez avoir. Au minimum vous aurez un test avec toutes les valeurs assignées, et si vous êtes pointilleux un deuxième avec toutes les valeurs à null pour contrôler qu’aucune NullPointerException n’est levée dans ce cas.

Et Optional ne fait pas déjà ça ?

La classe Optional de Java 8 sert en effet à gérer les cas null. Sauf que si vous appelez Optional.get() sans précaution et que la valeur interne est null, vous obtiendrez une exception au lieu de la valeur. En toute honnêteté je ne sais absolument pas pourquoi ils ont fait ça.

Bref ça ne résoudrait pas notre problème car on serait obligé d’écrire quelque chose du type :


B b = null;
if (optionalA.isPresent()) {
   b = optionalA.getValue();
}

Débloque les + belles offres tech en 10 mins

Cet article vous a plu ? Vous aimerez sûrement aussi :

 

JulienJulien
Moi c’est Julien, ingénieur en informatique avec quelques années d’expérience. Je suis tombé dans la marmite étant petit, mon père avait acheté un Apple – avant même ma naissance (oui ça date !). Et maintenant je me passionne essentiellement pour tout ce qui est du monde Java et du système, les OS open source en particulier.

Au quotidien, je suis devops, bref je fais du dév, je discute avec les opérationnels, et je fais du conseil auprès des clients.

Son Twitter - Son LinkedIn

Share Button

2 commentaires

  • Maximilien dit :

    Pour Optional, il faut utiliser orElse() et ses autres variantes qui permettent de récupérer un null plutot qu’une exception.

  • gojul dit :

    Bien vu, mais ça n’empêche que ça ne reste pas super pratique à utiliser notamment avec Hibernate et autres. Dommage, ils avaient proposé à un moment une syntaxe du type :

    a.getB()?.getC()?.getD()

    On la trouve d’ailleurs dans les JSP de mémoire. Ça aurait été bien pratique de l’avoir…

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Vous pouvez utiliser ces balises et attributs HTML : <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>