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
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());
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
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]);
Class
§La classe Class
contient des méthodes qui retournent des instances de
classes/interfaces définies dans le package java.lang.reflect
.
Field[] getDeclaredFields()
: renvoyer un tableau de tous les champs de la classeMethod[] getDeclaredMethods()
: renvoyer un tableau de toutes les méthodesConstructor[] getDeclaredConstructors()
: renvoyer tous les constructeursint getModifiers()
: renvoyer un entier qu'il faut décoder pour connaître les modificateurs de la classeListe non exhaustive, consultez la documentation.
XRayClass
.java.lang.String methods
ou java.lang.Integer constructors
).declared
renvoie à tout ce qui est déclaré dans la classe, quelle que soit la visibilité.
Sinon, ce sont seulement les membres publics qui sont retournés.for (int elt: tab) { //tab est de type int[]
System.out.println( elt );
}
Class<MaClasse> classe = (Class<MaClasse>) Class.forName(nomClasse);
MaClasse instance = classe.newInstance();
La méthode newInstance()
de la classe Class
présente plusieurs contraintes :
framework
dans lequel on peut injecter son propre code.main
,
qui ne doit pas changer, et d'une interface JeuCombinatoire
, qu'il
s'agit d'implémenter pour injecter ses propres jeux dans le framework.
Ces deux classes appartiennent au package
fr.insalyon.tc.framework
. En plus, le framework est distribué
avec le jeu de Wythoff. Regardez, compilez, testez.jeux
une classe Nim
implémentant JeuCombinatoire
.jeux
une classe EnsembleDeJeux
implémentant JeuCombinatoire
.jeux
.
Les deux joueurs jouent alternativement en choisissant un jeu
et un coup pour ce jeu. Quand il n'y a plus la possibilité
de jouer dans un jeu, la partie se poursuit sur les autres
jeux. Le joueur qui ne peut plus jouer dans le dernier jeu
non fini a perdu.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);
...
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.
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 :
extends NomClasse
), implémentation d'interface (implements NomInterface
)NomClasse nomObjet
),new NomClasse(...)
.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``.
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
getMethod
, newInstance
, etc.) ont un surcoût,Bref, la réflexivité ne devrait être utilisé que lorsqu'aucune autre forme de programmation n'est appropriée.