La réflexion en java

La réflexion en Java

Description

Tutoriel sur la réflexion en Java. On verra comment récupérer les constructeurs, méthodes et champs d'une classe en utilisant la réflexion. On verra également comment éxecuter une méthode, constructeur quelconque d'une classe.

Introduction

Bonjour, ça fait très longtemps que je n'ai pas posté sur ce site par manque de temps depuis le début de mon activité professionnelle, c'est qu'avant, quand j'étais étudiant, c'était beaucoup plus facile !!!

Pour reprendre en douceur, voici un petit tutoriel sur la réflexion en Java (rien à voir à l'activité de Réfléchir pour ceux qui ont déjà sortis l'aspirine !).

Pour un débutant en Java, cet article ne lui sera pas d'une grande utilité. Bien que simple, la réflexion peut paraître un peu superflue ou inutile mais avec un peu d'expérience dans des projets informatique d'envergure, la réflexion peut rendre bien des services.

Petite note sur le code présenté dans ce tutoriel : le code est prévu pour Java 6. Il est néanmoins très facile de le rendre compatible avec une version inférieure. En cas de difficulté, me poser la question.

Qu'est ce que la Réflexion ?

D'après Wikipédia,

En programmation informatique, la réflexion est la capacité d'un programme à examiner, et éventuellement à modifier, ses structures internes de haut niveau (par exemple ses objets) lors de son exécution.

Pour être plus clair, la réflexion c'est donner la possibilité au programme de pouvoir accéder/modifier la structure d'un objet pendant l'exécution du programme. Par structure d'un objet, on entend tout ce qui est propriété, classe, fonction etc.. En général, dans des langages « classiques » (C ou C++ par exemples), la structure d'un objet est uniquement connue au moment de la compilation, c'est-à-dire qu'il n'est pas possible, à l'exécution, de connaître « ce qu'a dans le ventre » un type d'objet quelconque.

Java implémente la réflexion. Il donne cependant uniquement la possibilité d'accéder aux structures et non pas de les modifier. Ainsi, à l'exécution d'un programme Java, il est tout à fait possible de connaître précisément la structure de n'importe quel objet et de pouvoir interagir avec (c'est à dire par exemple exécuter n'importe qu'elle fonction de l'objet) mais on ne peut pas par exemple, ajouter une fonction ou un champ à l'objet.

La structure d'un objet en Java est caractérisée par une classe qui contient des constructeurs, des méthodes (ou fonctions) et enfin des champs. La réflexion en Java permet d'avoir au moment de l'exécution la définition de n'importe quel objet tel que l'on avait programmé.

Mise en oeuvre

Le package java.lang.reflect est consacré à la réflexion. Comme vu plus haut, la structure d'un objet Java est caractérisée par une classe qui contient des constructeurs, des méthodes (ou fonctions) et enfin des champs. Les caractéristiques de l'objet sont représentés de manière formelle par une classe du package de réflexion :

Classe du package Représente
Class Une classe.
Method Une méthode d'une classe
Constructor Constructeur d'une classe
Field Un champ d'une classe

Notons, pour éviter une remarque en commentaire, que Class ne fait pas parti du package java.lang.reflect mais de java.lang, Néanmoins Class participe bien au mécanisme de la réflexion.

J'ai limité volontairement la liste des classes du package. Le but du présent tutoriel est de donner une première approche de la réflexion. Je laisserai donc le soin au lecteur de s'informer plus en détail s'il a besoin d'approfondir un peu.

Qu'est ce que ces classes nous apprennent sur l'objet ? La réponse est simple : tout !! Par exemple, à l'aide de Method, on peut connaître le nom de la méthode, les paramètres qu'elle prend et enfin le type de la valeur de retour.

Je vous recommande vivement de faire un tour sur la page suivante, qui est malheureusement pour certains, en anglais : http://java.sun.com/javase/6/docs/api/java/lang/reflect/package-summary.html

Pour mieux comprendre, prenons la classe suivante :

public class Test1
{
     private int unChamp2;
     public Test()3
     {
     }
     public int methode(String arg)4
     {
     }    
}

La structure de l'objet Test est donc la suivante :

  • 1 : Un Class représentant la classe Test
  • 2 : Un Field représentant le champ unChamp
  • 3 : Un Constructor représentant le constructeur de la classe
  • 4 : Un Method représentant la méthode methode

Pour accéder à toute la structure d'un objet, tout se fait à partir de Class.

Pour récupérer la classe d'une instance d'un objet, rien de plus simple, un simple getClass sur l'objet et le tour est joué :

Class classe=obj.getClass();

Il est également possible de récupérer la classe à partir d'un type d'objet. Par exemple, pour String :

Class classe=String.class;

A partir de là, pour récupérer (des exemples sont développés plus bas) :

  • Une méthode, utiliser getMethod()
  • Un constructeur, utiliser getConstructor()
  • Un champ, utiliser getField()

On a vu plus haut, que la réflexion ne servait pas seulement à accéder à la structure d'un objet mais aussi à interagir avec l'objet. Ainsi, on peut appeler une méthode quelconque, construire une instance à partir d'un constructeur ou affecter une valeur à un champ. Vous l'aurez compris, ces opérations sont réalisables à partir des classes Method, Constructor et Field.

Pour créer une nouvelle instance d'un objet, on utilise la fonction newInstance de Constructor. Cette fonction renvoie une nouvelle instance.

Ensuite, pour appeler une méthode, on utilise la fonction invoke de Method. Cette fonction permet d'exécuter la méthode sur une instance d'un objet.

Enfin, pour affecter une valeur à un champ, on utilise la fonction set de Field.

Nous allons mettre en pratique les notions vues jusqu'ici à travers plusieurs exemples pour mieux comprendre.

Exemples d'accès à la structure d'un objet

A travers les exemples ci-dessous, on va apprendre à utiliser la réflexion pour accéder à la structure d'un objet quelconque. Vous allez voir que c'est très simple.

Récupérer la classe d'un objet

Soit obj un objet quelconque, le code suivant donne sa Class. N'oublions pas que récupérer la classe est le point de départ pour avoir toutes les informations d'un objet

Class classe=obj.getClass();

Il est également possible de récupérer la classe d'un type par exemple de String :

Class classe=String.class ;

Récupérer une méthode

Du moment que l'on a récupéré la classe, on peut accéder aux méthodes de la classe.

Toutes les méthodes
Le code suivant donne toutes les méthodes de la classe dans un tableau.

import java.lang.reflect.Method; //ligne à rajouter en début de classe

Method methods * =classe.getMethods();

Récupérer une méthode particulière
Une méthode est identifiée par sa signature c'est à dire son nom et la liste des types de paramètres. Notez que la réflexion Java permet de remonter uniquement les méthodes en visibilité public (contrairement au CSharp).

Imaginons que l'on veuille la fonction concat qui prend comme paramètre une chaîne de caractères (String). Le code est le suivant :

Method concat=classe.getMethod("concat", String.class);

Le premier paramètre de getMethod est le nom de la méthode recherchée. Attention le nom est sensible aux majuscules/minuscules. Les paramètres qui suivent sont les types des paramètres de la fonction. Ici, on veut la fonction concat avec exactement un paramètre de type String.

Si vous essayez ce code, votre compilateur risque de râler sur les exceptions non gérées.

Exceptions levées :
Quand on utilise getMethod, deux exceptions sont susceptibles d'êtres levées. Ces exceptions doivent obligatoirement être gérées pour que le code plus haut soit correct.

  • NoSuchMethodException : quand la méthode demandée n'existe pas
  • SecurityException : quand votre code n'est pas autorisé à récupérer la méthode

Ainsi, le code plus haut complet pour qu'il compile est le suivant :

try {
    Method concat=classe.getMethod("concat", String.class);
} catch (SecurityException e) {
    //prb de sécurité
    e.printStackTrace();
} catch (NoSuchMethodException e) {
    //la méthode n'existe pas
    e.printStackTrace();
}

Récupérer un constructeur

Un constructeur, contrairement à une méthode, n'est pas identifié par son nom (puisque par définition, un constructeur porte toujours le nom de la classe) mais uniquement par le type de ses paramètres. Comme pour les méthodes, notez que la réflexion Java permet de remonter uniquement les constructeurs en visibilité public.

Le principe reste le même que pour les méthodes sauf qu'au lieu d'utiliser getMethod, on utilise getConstructor.

Tous les constructeurs

import java.lang.reflect.Constructor; //à rajouter au début du fichier
Constructor *  constructeurs=classe.getConstructors();

Récupérer un constructeur en particulier

try {
     Constructor constructeur=classe.getConstructor(StringBuilder.class);
} catch (SecurityException e) {
     //prb de sécurité
     e.printStackTrace();
} catch (NoSuchMethodException e) {
     //le constructeur n'existe pas
     e.printStackTrace();
}

Notez que les exceptions levées sont les mêmes que pour getMethod.

Récupérer un champ

Pour récupérer un champ, on utilise getField. Il faut encore noter que l'on récupère uniquement les champs en visibilité public.

Tous les champs

import java.lang.reflect.Field;
Field *  champs=classe.getFields();

Un champ en particulier
Un champ est identifié uniquement par son nom. Supposons que l'on veuille le champ name de l'objet :

try {
     Field champ=classe.getField("name");
} catch (SecurityException e) {
     //prb de sécurité
     e.printStackTrace();
} catch (NoSuchFieldException e) {
     //le champ n'existe pas 
     e.printStackTrace();
}

Quand le champ n'existe pas, c'est l'exception NoSuchFieldException qui est levée.

Exemples d'interactions avec un objet

Avec les exemples ci-dessus, vous voyez que je ne vous avez pas menti : la réflexion est très simple.

C'est bien beau de récupérer les méthodes et ses informations, mais ça serait encore plus beau si on pouvait interagir avec n'importe quel objet ! Par exemple, appeler une méthode quelconque ou construire une instance quelconque.

Une fois qu'on a les Method, Constructor, et Field, il est encore plus simple d'effectuer des opérations sur un objet.

Construire une instance à partir d'un Constructor

A partir de Constructor récupéré sur un type, il est très facile de construire une instance. On utilise pour cela la fonction newInstance. Cette fonction prend la liste des paramètres du constructeur.

En reprenant le constructeur récupéré plus haut, ce constructeur prend en paramètre un StringBuilder, il faut donc impérativement lui en passer un sous peine d'exception :

try {
     Object instance=constructeur.newInstance(new StringBuilder());
} catch (IllegalArgumentException e) {
    //le nombre d'arguments n'est pas bon
     e.printStackTrace();
} catch (InstantiationException e) {
     //la classe est abstraite (instance d'une classe abstraite impossible)
     e.printStackTrace();
} catch (IllegalAccessException e) {
     //le constructeur n'est pas accessible
     e.printStackTrace();
} catch (InvocationTargetException e) {
     //le constructeur a levé une exception
     e.printStackTrace();
}

La fonction newInstance va renvoyer la nouvelle instance du type.
Les exceptions qui peuvent être levées sont les suivantes :

  • IllegalArgumentException : le nombre d'arguments n'est pas bon ou ne sont pas du bon type
  • InstantiationException : lorsqu'on essaye d'instancier une classe abstraite (impossible en Java)
  • IllegalAccessException : le constructeur n'est pas accessible (est en visibilité privée par exemple)
  • InvocationTargetException : le constructeur a levé une exception

Appel à une méthode

A partir de l'objet Method, on peut exécuter la méthode sur une instance de l'objet. On utilise la fonction invoke qui prend en paramètre une instance d'un objet sur laquelle exécuter la méthode et la liste des paramètres de la méthode.

En reprenant la méthode récupérée dans l'exemple plus haut.

try {
     Object objet= " bonjour");
     Object resultat=concat.invoke(objet, " tout le monde");
} catch (IllegalArgumentException e) {
     //les arguments passés à la méthode ne sont pas bon
     e.printStackTrace();
} catch (IllegalAccessException e) {
     //fonction pas accessible
     e.printStackTrace();
} catch (InvocationTargetException e) {
     //la méthode a levée une exception
     e.printStackTrace();
}

Si la méthode exécutée doit renvoyer une valeur, cette valeur est renvoyée en retour de l'appel à invoke.

Les exceptions qui peuvent être levées sont les suivantes :

  • IllegalArgumentException : le nombre d'arguments n'est pas bon ou ne sont pas du bon type
  • IllegalAccessException : la méthode n'est pas accessible (est privée par exemple)
  • InvocationTargetException : la méthode a levé une exception

Affectation d'une valeur à un champ

Pour affecter une valeur à un champ d'une instance d'un objet, on utilise la méthode set de Field du champ à modifier.

try {
     champ.set(objet, "tuto");
} catch (IllegalArgumentException e) {
     //le parametre passé n'est pas valide (pas du bon type par exemple)
     e.printStackTrace();
} catch (IllegalAccessException e) {
     //fonction non accessible
     e.printStackTrace();
}

Les exceptions qui peuvent être levées sont les suivantes :

  • IllegalArgumentException : la valeur du champ à définir n'est pas du bon type
  • IllegalAccessException : le champ n'est pas accessible (est privé par exemple)

Lecture d'une valeur d'un champ

De la même manière, on peut lire la valeur d'un champ en utilisant la fonction get de Field.

try {
     Object lu=champ.get(objet);
} catch (IllegalArgumentException e) {
     //le parametre passé n'est pas valide (pas du bon type par exemple)
     e.printStackTrace();
} catch (IllegalAccessException e) {
     //fonction non accessible
     e.printStackTrace();
}

Exemple complet

Voici un exemple complet de réflexion. Etudiez ce code, il n'est vraiment pas compliqué, il regroupe toutes les notions vus dans ce tutoriel.

On défini 3 classes : A, B et C.

On va tirer au hasard une des trois classes. Sur cette classe, on affichera la liste des méthodes, des champs et des constructeurs en utilisant la réflexion.

Ensuite, toujours en utilisant la réflexion, une instance de la classe sera créée en utilisant un constructeur ayant un argument de type String s'il existe pour la classe.

On appellera ensuite la méthode, si elle existe, tutoriel sur l'instance qui vient d'être créé. Cette méthode doit prendre deux arguments de type String.

Pour finir, on affichera également les valeurs des champs de l'objet.

Voici le code complet, il doit être copié collé dans votre éditeur Java favori. L'exécution de l'exemple s'effectue en lançant simplement la classe ExempleComplet (contient une méthode main).

Fichier A.java

public class A
{
//**** Methodes ****
     private  int  champ1=45;
     public String champ2="valeur";
     protected double   champ3=2.0;
     public int    valA=4;
     //*** Constructeurs ****
     public A()
     {
     }
     public A(double val,String val2)
     {
     }
     private A(int val,String val2)
     {
     }
     public A(String a)
     {
     }
     //*** Méthodes ***
     public int compute()
     {
          System.out.println("Compute éxecuté !!!");
         return 0;
     }
     public void add(int a,int b)
     {
         System.out.println("add éxecuté !!!");
     }
     private void div(int a,int b)
     {
         System.out.println("div éxecuté !!!");
     }
     public String methodeA()
     {
         return "methodeA";
     }
}

Fichier B.java

public class B
{
     //**** Methodes ****
     private  String   joueur="toto";
     public int    score=454676;
     //*** Constructeurs ****
     public B()
     {
     }
     public B(String joueur)
     {
     }
     //*** Méthodes ***
     public int tutoriel(String a,String b)
     {
         System.out.println("tutoriel de B éxecuté !!!");
         return 0;
     }
     private  int  test()
     {
         System.out.println("test éxecuté !!!");
         return 1;
     }
     public String methodeB()
     {
         return "methodeA";
     }
}

Fichier C.java

public class C
{
     //**** Methodes ****
     private  String   unChamp="champ";
     public int    unChamp2=244;
     //*** Constructeurs ****
     public C()
     {
     }
     public C(String val)
     {
     }
     //*** Méthodes ***
     public int tutoriel(String a,String b)
     {
         System.out.println("tutoriel de C éxecuté !!!");
         return 20;
     }
     public String toString()
     {
          System.out.println("toString éxecuté !!!");
         return "Classe C";
     }
     public String methodeC()
     {
         return "methodeA";
     }
}

Fichier ExempleComplet.java

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class ExempleComplet
{
    /**
    * Point d'entrée dans le prg
    * @param args
    */
    public static void main(String *  args)
   {
         //Tableau des classes
         Class classes * ={A.class,B.class,C.class};

         //prenons une classe au hasard dans le tableau
         Class classe=classes[(int) (Math.random()*Integer.MAX_VALUE) % classes.length * ;

         //affiche a l'écran la classe choisie
         System.out.println("Classe choisie : "+classe.getName());

         //affichons la liste des constructeurs de cette classe
         System.out.println("*** Liste des constructeurs de la classe ****");
         Constructor constructeurs * =classe.getConstructors();
         for(Constructor constructeur : constructeurs)
         {
              System.out.println("Constructeur : "+constructeur.getName()+", Nb d'arguments : "+constructeur.getParameterTypes().length);
         }

         //affichons la liste des méthodes de cette classe
         System.out.println("*** Liste des méthodes de la classe ****");
         Method methodes * =classe.getMethods();
         for(Method methode : methodes)
         {
              System.out.println("Méthode : "+methode.getName()+", Nb d'arguments : "+methode.getParameterTypes().length+", Type en retour : "+(methode.getReturnType()==null ? null : methode.getReturnType().getName()));
         }

         //affichons la liste des champs
         System.out.println("*** Liste des champs de la classe ****");
         Field champs * =classe.getFields();
         for(Field champ : champs)
          {
              System.out.println("Champ : "+champ.getName()+", Type : "+champ.getType().getName());
         }

         //Récupere le constructeur ayant un parametre String
         System.out.println("*** Recupération du constructeur avec un parametre String ****");
         Constructor monConstructeur=null;
         try
         {
              monConstructeur=classe.getConstructor(String.class);
         } catch (SecurityException e)
         {
              System.out.println("Erreur de sécurité sur le constructeur");
              return;
         } catch (NoSuchMethodException e)
         {
              System.out.println("Le constructeur n'existe pas !");
              return;
         }

         //construction d'une instance de l'objet
         System.out.println("*** Création d'une instance à partir de ce constructeur ****");
         Object instance=null;
         try
         {
              instance=monConstructeur.newInstance("tuto");
         } catch (IllegalArgumentException e)
         {
              System.out.println("Erreur Argument invalide");
              return;
         } catch (InstantiationException e)
         {
              System.out.println("Erreur impossible d'instancier une classe abstraite");
              return;
         } catch (IllegalAccessException e)
         {
              System.out.println("Erreur constructeur par accessible");
              return;
         } catch (InvocationTargetException e)
         {
              System.out.println("Erreur exception levée par le constructeur");
              return;
         }

         //Récupération de la méthode tutoriel avec deux arguments String
         System.out.println("*** Récupération de la méthode tutoriel ****");
         Method tutoriel=null;
         try
         {
              tutoriel=classe.getMethod("tutoriel", String.class,String.class);
         } catch (SecurityException e)
         {
              System.out.println("Erreur de sécurité sur le constructeur");
              return;
         } catch (NoSuchMethodException e)
         {
              System.out.println("Erreur la méthode n'existe pas");
              return;
         }
         
         //Execution de la méthode tutoriel
         System.out.println("*** Execution de la méthode tutoriel ****");
         try
         {
              Object retour=tutoriel.invoke(instance, "un","deux");
              System.out.println("Valeur en retour="+(retour == null ? null : retour.toString()));
         } catch (IllegalArgumentException e)
         {
              System.out.println("Erreur argument invalide");
              return;
         } catch (IllegalAccessException e)
         {
              System.out.println("Erreur la méthode n'est pas accessible");
              return;
         } catch (InvocationTargetException e)
         {
              System.out.println("Erreur la méthode a provoquée une exception");
              return;
         }

         //Affichage des valeurs des champs
         System.out.println("*** Liste des valeurs des champs ****");
         for(Field champ : champs)
         {
              try
              {
                   Object valeur=champ.get(instance);
                   System.out.println("Valeur du champ "+champ.getName()+" : "+(valeur == null ? null : valeur.toString()));
              } catch (IllegalArgumentException e)
              {
                   System.out.println("Erreur sur le champ "+champ.getName()+", argument non valide");
              } catch (IllegalAccessException e)
              {
                   System.out.println("Erreur sur le champ "+champ.getName()+" n'est pas accessible");
              }
         }
     }
}

Résultats d'exécutions

Quand la classe A est choisie :
-------------------------
Classe choisie : A

*** Liste des constructeurs de la classe ****

Constructeur : A, Nb d'arguments : 1

Constructeur : A, Nb d'arguments : 2

Constructeur : A, Nb d'arguments : 0

*** Liste des méthodes de la classe ****

Méthode : compute, Nb d'arguments : 0, Type en retour : int

Méthode : methodeA, Nb d'arguments : 0, Type en retour : java.lang.String

Méthode : add, Nb d'arguments : 2, Type en retour : void

Méthode : wait, Nb d'arguments : 0, Type en retour : void

Méthode : wait, Nb d'arguments : 2, Type en retour : void

Méthode : wait, Nb d'arguments : 1, Type en retour : void

Méthode : hashCode, Nb d'arguments : 0, Type en retour : int

Méthode : getClass, Nb d'arguments : 0, Type en retour : java.lang.Class

Méthode : equals, Nb d'arguments : 1, Type en retour : boolean

Méthode : toString, Nb d'arguments : 0, Type en retour : java.lang.String

Méthode : notify, Nb d'arguments : 0, Type en retour : void

Méthode : notifyAll, Nb d'arguments : 0, Type en retour : void

*** Liste des champs de la classe ****

Champ : champ2, Type : java.lang.String

Champ : valA, Type : int

*** Recupération du constructeur avec un parametre String ****

*** Création d'une instance à partir de ce constructeur ****

*** Récupération de la méthode tutoriel ****

Erreur la méthode n'existe pas
-------------------------
Si la liste des méthodes affichée vous parait suspecte, n'oubliez pas qu'en Java tout objet hérite de Object donc aussi de ses méthodes ! (méthodes wait, hashCode, getClass, equals, toString, notify et notifyAll).

Quand la classe B est choisie :
-------------------------
Classe choisie : B

*** Liste des constructeurs de la classe ****

Constructeur : B, Nb d'arguments : 0

Constructeur : B, Nb d'arguments : 1

*** Liste des méthodes de la classe ****

Méthode : tutoriel, Nb d'arguments : 2, Type en retour : int

Méthode : methodeB, Nb d'arguments : 0, Type en retour : java.lang.String

Méthode : wait, Nb d'arguments : 0, Type en retour : void

Méthode : wait, Nb d'arguments : 2, Type en retour : void

Méthode : wait, Nb d'arguments : 1, Type en retour : void

Méthode : hashCode, Nb d'arguments : 0, Type en retour : int

Méthode : getClass, Nb d'arguments : 0, Type en retour : java.lang.Class

Méthode : equals, Nb d'arguments : 1, Type en retour : boolean

Méthode : toString, Nb d'arguments : 0, Type en retour : java.lang.String

Méthode : notify, Nb d'arguments : 0, Type en retour : void

Méthode : notifyAll, Nb d'arguments : 0, Type en retour : void

*** Liste des champs de la classe ****

Champ : score, Type : int

*** Recupération du constructeur avec un parametre String ****

*** Création d'une instance à partir de ce constructeur ****

*** Récupération de la méthode tutoriel ****

*** Execution de la méthode tutoriel ****

tutoriel de B éxecuté !!!

Valeur en retour=0

*** Liste des valeurs des champs ****

Valeur du champ score : 454676
-------------------------

Quand la classe C est choisie :
-------------------------
Classe choisie : C

*** Liste des constructeurs de la classe ****

Constructeur : C, Nb d'arguments : 0

Constructeur : C, Nb d'arguments : 1

*** Liste des méthodes de la classe ****

Méthode : tutoriel, Nb d'arguments : 2, Type en retour : int

Méthode : methodeC, Nb d'arguments : 0, Type en retour : java.lang.String

Méthode : toString, Nb d'arguments : 0, Type en retour : java.lang.String

Méthode : wait, Nb d'arguments : 0, Type en retour : void

Méthode : wait, Nb d'arguments : 2, Type en retour : void

Méthode : wait, Nb d'arguments : 1, Type en retour : void

Méthode : hashCode, Nb d'arguments : 0, Type en retour : int

Méthode : getClass, Nb d'arguments : 0, Type en retour : java.lang.Class

Méthode : equals, Nb d'arguments : 1, Type en retour : boolean

Méthode : notify, Nb d'arguments : 0, Type en retour : void

Méthode : notifyAll, Nb d'arguments : 0, Type en retour : void

*** Liste des champs de la classe ****

Champ : unChamp2, Type : int

*** Recupération du constructeur avec un parametre String ****

*** Création d'une instance à partir de ce constructeur ****

*** Récupération de la méthode tutoriel ****

*** Execution de la méthode tutoriel ****

tutoriel de C éxecuté !!!

Valeur en retour=20

*** Liste des valeurs des champs ****

Valeur du champ unChamp2 : 244
-------------------------

Conclusion

Pour conclure, comme vous pouvez le constater, la réflexion est très simple et ouvre de nombreuses possibilités. Néanmoins, sous prétexte que vous avez appris un nouveau concept, ce n'est pas une raison pour l'utiliser à toutes les sauces ! Il est parfois bien plus simple d'utiliser des interfaces ou des classes abstraites.

Un des inconvénients de la réflexion, c'est le manque de lisibilité du code. La réflexion est utile pour effectuer des traitements automatiques sur le contenu des objets. Personnellement, dans un projet de site web, pour afficher toutes les informations d'un objet dans une page automatiquement (c'est-à-dire sans se farcir un à un les accès à tous les champs de l'objet), l'utilisation de la réflexion a été pratique et m'a fait gagné un temps fou. En effet, dans chaque page, en parcourant le contenu d'un objet par réflexion, en quelques lignes, j'assure qu'a la moindre modification structurelle de l'objet (par exemple on ajoute un champ dans celui ci) que les répercutions soient faites automatiquement sans effort dans toutes les pages affichant cet objet.

Sur ce, je vous souhaite une bonne Java !! (ah ah c'est fou l'humour que j'ai ! )

A voir également
Ce document intitulé « La réflexion en java » issu de CodeS SourceS (codes-sources.commentcamarche.net) est mis à disposition sous les termes de la licence Creative Commons. Vous pouvez copier, modifier des copies de cette page, dans les conditions fixées par la licence, tant que cette note apparaît clairement.
Rejoignez-nous