Différences

Cette page vous donne les différences entre la révision choisie et la version actuelle de la page.

blog:2008-07-16-introspection_et_types_parametres_en_java 2008/07/16 22:36 version actuelle
Ligne 1: Ligne 1:
 +~~META:
 +date created = 2007-06-19 14:46:34
 +~~
 +
 +====== Introspection et types paramétrés en Java ======
 +
 +Plusieurs fois déjà, j'ai eu recours à l'introspection pour extraire la structure de donnée encapsulée dans une classe Java. Avec quelques méthodes classiques des classes [[http://java.sun.com/javase/6/docs/api/java/lang/Class.html|''Class'']] et [[http://java.sun.com/javase/6/docs/api/java/lang/reflect/Field.html|''Field'']], on réussit à extraire pas mal de chose :
 +  * Dans un objet de type ''Class'', ''getDeclaredFields'' permet d'obtenir la liste des attributs de cette classe, et ''getSuperclass'' permet de naviguer dans les classes parentes de l'arbre d'héritage pour récupérer les attributs hérités.
 +  * Dans un objet de type ''Field'', ''getName()'' donne le nom de cet attribut et ''getDeclaringClass'' donne son type déclaré (l'instance pouvant être d'un type héritant de ce type déclaré).
 +
 +
 +Viennent ensuite les types paramétrés qui contiennent de l'information supplémentaire sur la structure de données. En effet un attribut de type ''List<Integer>'', ne sera considéré que comme un attribut de type ''List'' avec les méthodes précédentes. Or, le fait que cette liste contiennent des entiers est une information importante. De même un attribut de type ''List<List<MaClasse>>'', n'est pas une vulgaire liste, mais bien un élément complexe de la structure de donnée. Il est donc important de bien gérer ces types paramétrés lors d'une telle introspection.
 +
 +======  ======
 +
 +Un premier coup d'œuil à la documentation nous attire sur la méthode ''getTypeParameters'' de la classe ''Class''. Cependant, attention, cette méthode ne nous sera pas très utile car elle ne renseigne que le paramétrage d'une classe seule. Ainsi, lors de l'introspection d'une classe ayant un attribut de type ''List<Integer>'', les seules informations récupérées avec cette méthode seront que la classe de cet attribut, qui est ''List<E>'', a un type paramétré qui s'appelle ''E''. On n'est pas très avancé pour ce que l'on veut faire.
 +
 +Il faut donc se tourner vers la déclaration de ces attributs, et travailler avec nos objets ''Field''. Dans un premier temps, il faut récupérer le type (de classe ''Type'') de cet attribut avec la méthode ''getGenericType''. Puis la méthode ''getActualTypeArguments'' va nous informer très concrètement de la nature du paramétrage de notre attribut (enfin !). Cette méthode nous renvoie donc un tableau, dont chaque élément peut être de cinq types différents héritant tous de ''Type'', en fonction de la nature du type paramétré :
 +
 +  * ''Class'' : c'est le cas le plus simple, et certainement le plus classique. Cela signifie que votre type paramétré est tout simplement une classe. C'est l'exemple de notre attribut de type ''List<Integer>'', le type paramétré est ''Integer''.
 +  * ''ParameterizedType'' : notre type paramétré est lui-même paramétré par un autre type. C'est le cas par exemple, d'un attribut qui serait de type ''List<List<Integer>>''. Il ne reste donc plus qu'à analyser de la même manière les types paramétrés de ce type, et on pourra récupérer le type de base avec la méthode getRawType de la classe ''ParameterizedType''
 +  * ''WildcardType'' : notre type paramétré est exprimé avec un joker, du style ''<? extends Collection>'' ou ''<? super Collection>''. On peut alors récupérer le type à partir duquel est exprimé ce joker (ici ''Collection'') avec la méthode ''getLowerBounds'' ou ''getUpperBounds'' de la classe ''WildcardType''
 +  * ''GenericArrayType'' : notre type paramétré est de type tableau, ce qui arriverait si notre attribut était déclaré de type ''List<Integer []>''. Nous pouvons récupérer le type des éléments du tableau avec la méthode ''getGenericComponentType'' de la classe ''GenericArrayType''.
 +  * ''TypeVariable'' :  dans ce cas, le type paramétré est exprimé à l'aide d'une variable. Ce qui pourrait être le cas dans l'exemple suivant :
 +<code java>public class MaClasse<T extends Collection> {
 +  private List<T> maListe;
 +  …
 +</code>
 +On peut alors récupérer la limite des types possibles avec la méthode ''getBounds'' de la classe ''TypeVariable''.
 +
 +
 +Pour terminer, quelques références pour approfondir le sujet :
 +
 +  * [[http://java.developpez.com/faq/java/?page=langage_reflex|La section sur l'introspection dans la FAQ de java.developpez.com]]
 +  * [[http://ricky81.developpez.com/tutoriel/java/api/reflection/|Un cours sur l'API Reflection]]
 +  * [[http://lroux.developpez.com/article/java/tiger/?page=page_5#Lgenerics|Un cours sur les types paramétrés introduits avec Java 5]]
 +  * [[http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf|Le cours de Sun sur les types paramétrés]]
 +  * [[http://www.ibm.com/developerworks/library/j-cwt11085.html|Un article de Dennis Sosnoski chez IBM sur l'introspection des types génériques]]
 +
 +{{tag>java}}
 +
 +~~LINKBACK~~
 +~~DISCUSSION~~

Afficher la pageAnciennes révisionsDerniers changements

Copyright © Nicolas Dumoulin, 2008 — Droits