:: Enseignements :: Master :: M1 :: 2014-2015 :: Java Avancé ::
[LOGO]

Reflection et implantation de Map


Exercice 1 - Introspector

Le but de cet exercice est d'implanter une méthode introspect qui prend un objet quelconque et voit celui-ci comme une Map qui associe à une chaine de caractère la valeur du getter correspondant.
Par exemple, si une classe Bar possède un méthode getFoo, alors si on appel introspect avec une instance de la classe Bar alors introspect va renvoyer un table de hachage qui pour la clé "foo" possède la valeur de retour de la méthode getFoo.

En fait, pour vous aider, une partie du code de la classe Introspectors a déjà été écrit
.
  • Compléter le code de la méthode getValueByReflection pour que le code marche.
    Comment doit-on gérer l'exception IllegalArgumentException, noter que c'est une RuntimeException ?
    Comment doit-on gérer l'exception IllegalAccessException ?
    Que contient la cause de l'exception InvocationTargetException, comment doit-on la gérer l'exception InvocationTargetException ?
  • Pourquoi l'appel Class.getMethods() fait nécessairement des copies défensives ?
    Note: Regarder le type de retour de getMethods() et le fait que Method possède une méthode setAccessible.
  • Comment améliorer le code en utilisant la classe ClassValue comme un cache ?
    Modifier le code de la méthode introspect pour utiliser le cache.
  • Modifier le code qui créé le cache pour stocker des Map<String,Method>.
    Si vous ne voyez pas pourquoi, vous pouvez lire la fin du sujet :)
    Vous pouvez écrire la code de création du Map<String,Method> en utilisant un Stream sur les méthodes et en appelant Collectors.toMap(keyProjection, valueProjection).
  • On souhaite enfin que les modifications postérieures à la création de la Map soit reflétées dans la Map.
           java.awt.geom.Point2D point = new java.awt.geom.Point2D.Double(1, 2);
           Map<String, Object> map2 = Introspectors.introspect(point);
           System.out.println(map2);  // { x = 1, y = 2, ... }
           point.setLocation(7, 13);
           System.out.println(map2);  // { x = 7, y = 13, ... }
          
    Ce veut donc dire que la Map renvoyée dois agir comme une vue de l'objet et qu'il ne faut pas calculer les valeurs associées à chaque getter dans la méthode introspect.
    Rappel: il existe une classe AbstractMap.
  • Enfin, faite en sorte que le test testSlooooow passe.

Le test JUnit est ici IntrospectorsTest.java.

Exercice 2 - Introspectors 2 [A la maison]

L'introspector que nous avons écrit dans l'exercice 1 est uni-directionel, les changements fait sur l'objet sont bien reportés sur la Map mais le contraire n'est pas vrai. Un changement de valeur dans la Map, avec un put par exemple, n'appel pas le setter de l'objet (si celui-ci existe).
On se propose d'implanter ce changement.

  1. Faire en sorte qu'un appel à put ou putAll sur la Map renvoyé par la méthode introspect de la classe Introspectors2 appel le ou les setters correspondant sur l'objet.