Les FAQs Java :
FAQ JAVA FAQ Java EE FAQ Java ME FAQ Java XML FAQ JavaFX FAQ Java GUI FAQ Struts FAQ JSF FAQ JDBC JDO FAQ Hibernate FAQ Spring FAQ Eclipse FAQ NetBeans FAQ JCreator FAQ Maven 2

FAQ JavaConsultez toutes les FAQ

Nombre d'auteurs : 53, nombre de questions : 231, dernière mise à jour : 26 janvier 2014 

 
OuvrirSommaireGénéralitésLa reflexivité

L'introspection consiste en la découverte dynamique des informations propres à une classe Java ou à un objet. Ce mécanisme est notamment utilisé au niveau de la machine virtuelle Java lors de l'exécution de votre programme, et donne lieu à une API.

Le paquetage java.lang.reflect permet l'introspection en rendant possible l'accès aux classes, à leurs champs, méthodes ou encore constructeurs, et à toutes les informations les caractérisant, même celles qu'on pensaient inaccessibles Elle est également très utile pour instancier des classes de manière dynamique, dans le processus de sérialisation d'un bean Java, ainsi que dans la génération de code.

Les méta données présentes dans les fichiers binaires renseignent sur le contenu de chaque classe répertoriée et permettent à la jvm de procéder à des vérifications lors de l'exécution d'un programme (pensez à l'exception java.lang.NoSuchMethodError).
La jvm utilise également ces informations pour vous proposer la complétion de code dans les environnements de développement Java, ce qui se fait en temps réel (pas de génération à faire au préalable).

Des détails sur le format des méta données dans un fichier binaire sont disponibles dans les documents de spécification de la machine virtuelle Java. Sachez seulement que les champs et méthodes sont identifiés par leur nom, le type (identifiants spécifiques à la jvm) pour les champs, et la signature pour les méthodes. A partir de ces informations, la jvm sait directement localiser la portion de byte code correspondant à l'implémentation d'une méthode.

Créé le 10 août 2004  par Ricky81

Lien : API Reflection

Il existe dans la classe Class une méthode nommée getSuperClass(), c'est cette méthode que nous allons utiliser.

 
Sélectionnez

Class c = Class.forName("maClasse");
while((c=c.getSuperclass()) != null)
{
   System.out.println(c.getName());
}
Créé le 10 août 2004  par Ricky81

Lien : API Reflection

Il existe dans la classe Class une méthode nommée getInterfaces() qui renvoie un tableau des interfaces implémentées par la classe.

 
Sélectionnez

Class c = Class.forName("maClasse");
Class[] interfaces = c.getInterfaces();
for(int i=0;i<interfaces.length;++i)
{
   System.out.println(interfaces[i].getName());
}
 
Mis à jour le 12 octobre 2006  par Ricky81

Lien : API Reflection

Il existe dans la classe Class une méthode nommée getPackage() qui renvoie un objet de type java.lang.Package.

 
Sélectionnez

 
Class c = Class.forName("monPackage.maClasse");
Package p = c.getPackage();
System.out.println(p.getName());
Créé le 10 août 2004  par Ricky81

Lien : API Reflection

La liste des méthodes publiques (même celles héritées) est disponible grâce à la méthode getMethods().

 
Sélectionnez

Class c = Class.forName("maClasse");
java.lang.reflect.Method[] m = c.getMethods();

Il est également possible de récupérer une méthode par son nom et sa signature en utilisant la méthode :

 
Sélectionnez
getMethod(String name, Class[] parameterTypes)
Créé le 10 août 2004  par Ricky81

Lien : Est-il possible d'avoir la liste des champs/méthodes privés et protégés d'une classe ?
Lien : Comment récupérer la liste des champs d'une classe ?
Lien : API Reflection

La classe java.lang.reflect.Method dispose d'un certain nombre de méthodes permettant de reconstituer la signature d'une méthode. Voici un exemple de deux d'entre elles :

 
Sélectionnez

// m est un objet de type Method
Class r = m.getReturnType();
Class[] params = m.getParameterTypes();
 
Créé le 10 août 2004  par Ricky81

Lien : API Reflection

Il existe dans la classe Class une méthode nommée getFields(), c'est cette méthode que nous allons utiliser.

 
Sélectionnez

Class c = Class.forName("maClasse");
java.lang.reflect.Field[] f = c.getFields();

Il est également possible de récupérer un champ par son nom en utilisant la méthode getField(String name).

Créé le 10 août 2004  par Ricky81

Lien : Est-il possible d'avoir la liste des champs/méthodes privés et protégés d'une classe ?
Lien : Comment récupérer la liste des méthodes d'une classe ?
Lien : API Reflection

Il existe une classe dans java.lang.reflect appelée Modifier.
Cette classe gère l'ensemble des informations définies pour un champ ou une méthode, à savoir : la visibilité, l'attribut "constante" ainsi que le caractère statique. Ce sont essentiellement des méthodes de classe qui permettent de consulter ces caractéristiques à partir d'un entier.

 
Sélectionnez

// m est un objet de type Method
int mod = m.getModifiers();
if(java.lang.reflect.Modifier.isStatic(mod))
{
   System.out.println("méthode statique");
}
Créé le 10 août 2004  par Ricky81

Lien : Comment connaître la signature d'une méthode ?
Lien : Comment déterminer l'ensemble des informations concernant un champ ?
Lien : API Reflection

Il existe bien entendu les méthodes getName() et getType() qui renvoie des le nom et le type du champ. Une dernière méthode permet d'obtenir les informations complémentaires : getModifiers(). Nous nous retrouvons avec un entier qu'il faut analyser à l'aide de la classe java.lang.reflect.Modifier. Nous allons ici utiliser la méthode statique toString() pour obtenir ces informations sous la forme d'une chaîne de caractères.

 
Sélectionnez
// f est un objet de type Field
int mod = f.getModifiers();
System.out.println(java.lang.reflect.Modifier.toString(mod));

Avec les infos de la méthode getModifiers(), vous pouvez aussi définir via la classe Modifier si les informations contiennent quelque chose de spécifique, via les méthodes isXXX, par exemple :

 
Sélectionnez
// f est un objet de type Field
int mod = f.getModifiers();
System.out.println("f est static = " + Modifier.isStatic(mod));
System.out.println("f est transient = " + Modifier.isTransient(mod));
System.out.println("f est volatile = " + Modifier.isVolatile(mod));
...
Mis à jour le 7 janvier 2007  par Ricky81 , Baptiste Wicht

Lien : Comment connaître la signature d'une méthode ?
Lien : API Reflection

Pour consulter ou modifier un champ donné d'un objet de façon dynamique, il faut commencer par récupérer l'objet de type Field correspondant au champ en question. Il suffit ensuite d'appeler la méthode correspondante avec pour premier paramètre l'objet cible.
Prenons l'exemple suivant où nous modifions le contenu du champ défini par la variable nomChamp de l'objet obj en lui donnant la valeur définie par la variable val.

 
Sélectionnez

void changeValeur(Object obj, String nomChamp, Object val) throws Exception
{
  java.lang.reflect.Field f = obj.getClass().getField(nomChamp);
   f.set(obj,val);
}

Un exemple de consultation de la valeur d'un champ donné :

 
Sélectionnez

void afficheValeur(Object obj, String nomChamp) throws Exception
{
   Field f = obj.getClass().getField(nomChamp);
   System.out.println(f.get(obj));
}

Remarque : les methodes set et get sont des méthodes générales mais il existe aussi des équivalents pour les types classiques : setDouble(Object obj, double d) ou setBoolean(Object obj, boolean z).

Créé le 10 août 2004  par Ricky81

Lien : Comment lancer dynamiquement une méthode donnée d'un objet ?
Lien : Est-il possible d'avoir la liste des champs/méthodes privés et protégés d'une classe ?
Lien : Y a-t-il un moyen de consulter et/ou de modifier la valeur d'un champ privé ?
Lien : API Reflection

Nous allons utiliser la méthode invoke définie dans la classe Method :

 
Sélectionnez
Object invoke(Object obj, Object[] args)

Voici un exemple générique de lancement dynamique d'une méthode donnée sur un objet :

 
Sélectionnez

Object lancerMethode(Object obj, Object[] args, String nomMethode) throws Exception
{
   Class[] paramTypes = null;
   if(args != null)
   {
      paramTypes = new Class[args.length];
      for(int i=0;i<args.length;++i)
      {
         paramTypes[i] = args[i].getClass();
      }
   }
   Method m = obj.getClass().getMethod(nomMethode,paramTypes);
   return m.invoke(obj,args);
}

A noter que cette méthode ne fonctionne que pour les types exacts de classe pour les paramètres. C'est-à-dire qu'on ne pourra pas utiliser une classe fille comme argument de paramètre.

Mis à jour le 29 octobre 2008  par Ricky81

Lien : Comment lancer dynamiquement une méthode de classe donnée ?
Lien : Comment accéder dynamiquement à la valeur d'un champ donné d'un objet ?
Lien : Comment passer les types primitifs en paramètre lors de l'utilisation de la réflexivité ?
Lien : API Reflection

Les types primitifs (byte, char, short, int, long, float, double, boolean) ont tous des wrapper dans le package java.lang. Respectivement: Byte, Character, Short, Integer, Long, Float, Double, Boolean.

Chacune de ces classes contient une variable static TYPE de type Class. C'est cette classe qu'il faut utiliser pour spécifier le type du paramètre; la valeur quand a elle sera contenue dans un objet du type du wrapper.

Exemple: Appel d'une méthode prenant un int en paramètre.

Dans cet exemple nous allons appeler la méthode statique abs(int) de la classe java.lang.Math

 
Sélectionnez
  Class types[] = { Integer.TYPE }; 
  Method method = Math.class.getMethod("abs", types); 
  Object parametres[] = { new Integer(-1) }; 
  Integer iWrap = (Integer) method.invoke(null, parametres); 
  System.out.println("Valeur absolue de -1 = " + iWrap);  
Créé le 19 juillet 2004  par bulbo

Lien : Comment lancer dynamiquement une méthode donnée d'un objet ?
Lien : API Reflection

Pour lancer dynamiquement une méthode de classe, le principe est le même que pour une méthode sur un objet (voir lien). La signature de la méthode (classe Method) à utiliser étant :

 
Sélectionnez
Object invoke(Object obj, Object[] args)

Lorsque la méthode est de classe, le paramètre obj n'est pas évalué. Vous pouvez mettre n'importe quel objet ou tout simplement null.

Créé le 10 août 2004  par Ricky81

Lien : Comment lancer dynamiquement une méthode donnée d'un objet ?
Lien : Comment savoir si une méthode ou un champ est de classe ?
Lien : API Reflection

Après avoir récupéré un objet sur un champ privé (voir lien), vous pouvez tenter de désactiver la protection en utilisant la méthode setAccessible(boolean b). Si l'utilisation de cette méthode ne provoque pas le déclenchement d'une exception par un SecurityManager, vous allez pouvoir modifier la valeur du champ.

Exemple : prenons une classe Secret avec un champ privé priv de type String.

 
Sélectionnez

void modifierChamp(Secret s, String val)
{
   Field f = s.getClass().getDeclaredField("priv");
   f.setAccessible(true);
   f.set(s,val);
}
Créé le 10 août 2004  par Ricky81

Lien : Est-il possible d'avoir la liste des champs/méthodes privés et protégés d'une classe ?
Lien : API Reflection

Les moyens mis à disposition par l'API Reflection permettent de passer outre les règles de l'encapsulation. Vous pourrez consulter les champs et méthodes privés/protégés de la même manière que les champs et méthodes publiques, mais en utilisant les méthodes getDeclaredFields et getDeclaredMethods (ainsi que leurs variantes) au lieu de getFields et getMethods.

Exemple :

 
Sélectionnez

Class c = Class.forName("maClasse");
java.lang.reflect.Field[] f = c.getDeclaredFields();

Remarque : contrairement aux méthodes getFields et getMethods, getDeclaredFields et getDeclaredMethods ne renvoient pas les informations héritées. Dans ce cas, il est nécessaire d'aller interroger la classe mère.

Créé le 10 août 2004  par Ricky81

Lien : Y a-t-il un moyen de consulter et/ou de modifier la valeur d'un champ privé ?
Lien : API Reflection

Java 5.0 permet de marquer certains éléments du langage avec des Annotations, ces dernières peuvent être accessibles lors de l'exécution (seulement pour les annotations dont la rétention est RetentionPolicy.RUNTIME). Le package java.lang.reflect se voit ainsi doté d'une nouvelle interface qui décrit quatre méthodes permettant d'accéder aux annotations, on y trouve ainsi les méthodes suivantes :

  • getAnnotation(Class) qui permet d'obtenir une annotation particulière (si elle est présente).
  • getAnnotations() qui permet d'obtenir un tableau contenant toutes les annotations de l'élément.
  • getDeclaredAnnotations() qui permet d'obtenir un tableau contenant toutes les annotations directement déclarées sur l'élément (en ignorant ainsi les annotations héritées de la classe parent).
  • isAnnotationPresent(Class) qui permet simplement de savoir si une annotation particulière est présente.

Cette interface, nomméee AnnotatedElement, est implémentée par les classes suivantes : Class, Package, Constructor, Method et Field. Enfin les classes Constructor et Method proposent également une méthode getParameterAnnotations() afin d'accéder aux annotations de leurs paramètres...

Créé le 22 août 2005  par adiGuba

Lien : [Java 5.0] Qu'est-ce qu'une annotation ?
Lien : API Reflection
Lien : Tutoriel : Les Annotations de Java 5.0
Lien : java.lang.reflect.AnnotatedElement

Les codes sources présentés sur cette page sont libres de droits, et vous pouvez les utiliser à votre convenance. Pour le reste, ce document constitue une oeuvre intellectuelle protégée par les droits d'auteurs. Ce document issu de http://www.developpez.com est soumis à deux licences, en fonction des contributeurs : - Les contributions de Clément Cunin et Johann Heymes sont soumises aux termes de la la licence GNU FDL traduite en français ici. Permission vous est donnée de distribuer, modifier des copies des contributions de Clément Cunin et Johann Heymes tant que cette note apparaît clairement : "Ce document issu de http://www.developpez.com est soumis à la licence GNU FDL traduite en français ici. Permission vous est donnée de distribuer, modifier des copies de cette page tant que cette note apparaît clairement". - Pour ce qui est des autres contributions : Copyright © 2014 Developpez LLC : Tous droits réservés Developpez LLC. Aucune reproduction, ne peut en être faite sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages et intérêts. Cette page est déposée à la SACD.