Réflexivité§

Inspection des classes§

Java est un langage réflexif§

Java est un langage réflexif : il donne la possibilité pour un programme en cours d'exécution d'examiner son propre état et d'agir sur ce dernier.

Cette caractéristique de Java est très utilisée notamment

Un exemple du langage§

Toutes les classes dérivent par défaut de Object, qui possède une méthode toString. Par conséquent, tous les objets sont transformables en chaîne de caractère et affichables.

Le message affiché par défaut contient le nom de la classe, car la méthode toString de Object retourne une chaîne de caractère donnée par:

getClass().getName() + '@' + Integer.toHexString(hashCode());

La classe Class§

Le package java.lang comporte une classe appelée Class. Au chargement d'une classe, la machine virtuelle crée automatiquement une instance de Class permettant d'obtenir tous les renseignements possibles concernant la classe chargée.

On obtient une instance de Class de trois manières différentes :

Class<String> classe
  = (Class<String>) Class.forName("java.lang.String"); //by name
String aString = "azerty"; //from an object
Class<String> classe = (Class<String>) aString.getClass();
Class<String> classe = String.class; //from a class literal

Généricité§

Comme vous le voyez, depuis java 5, la classe Class est paramétrée par un type. Par exemple, Class<String> est le type de l'objet créé par la machine virtuelle au chargement de la classe String.

Class<String> classe
  = (Class<String>) Class.forName("java.lang.String");

Mais parfois ce type ne peut être connu lors de l'écriture du programme. Dans ce cas, on peut utiliser le joker ? :

Class<?> yourClass = Class.forName(args[0]);

Les méthodes de Class§

La classe Class contient des méthodes qui retournent des instances de classes/interfaces définies dans le package java.lang.reflect.

Liste non exhaustive, consultez la documentation.

Ex.1. Inspecteur (5 min)§

for (int elt: tab) { //tab est de type int[]
    System.out.println( elt );
}

Code dynamique§

Instancier une classe§

Class<MaClasse> classe = (Class<MaClasse>) Class.forName(nomClasse);
MaClasse instance = classe.newInstance();

La méthode newInstance() de la classe Class présente plusieurs contraintes :

Ex.2. Framework / Prise en main (5 min)§

Ex.3. Framework / Jeu de Nim (10 min)§

Ex.4. Framework / Ensemble de jeux (30 min)§

Quelques trucs pour aller plus vite§

Obtenir le répertoire du classpath :

String nomRepertoire = System.getProperty("java.class.path");

Obtenir la liste des fichiers d'un répertoire :

File repertoire = new File(nomRepertoire);
for (String nom : repertoire.list()) {}

Traitement des chaines de caractère :

...
String[] decomposition = chaine.split(separateur);
boolean flag = chaine.endsWith(extension);
String sousChaine = chaine.substring(pos1,pos2);
int n = Integer.parseInt(chaine);
...

Note sur les paramètres§

Il est possible d'instancier une classe par un constructeur possédant des paramètres. Dans ce cas, il s'agit de récupérer le constructeur qu'on souhaite utiliser à partir de sa signature et de sa classe, puis d'instancier la classe en fournissant la liste des arguments.

Selon le même procédé, il est possible de récupérer une méthode, puis de l'appeler.

Consultez la documentation.

Conclusion§

Injection de dépendances§

Dans un projet, il y a des dépendances statiques, c'est-à-dire des classes (ou interfaces) qui apparaissent dans le code d'une classe :

L'injection de dépendances consiste principalement à supprimer ce dernier type de dépendance statique, très forte, en injectant à l'exécution les classes apropriées à l'aide de la réflexivité. Bref, on supprime les ``new``.

Le coût§

La réflexivité de Java contribue à sa flexibilité et à réduire les dépendances, mais elle a un coût à prendre en compte pour envisager son usage, car

Bref, la réflexivité ne devrait être utilisé que lorsqu'aucune autre forme de programmation n'est appropriée.

Capacités/connaissances§