précédent | suivant | table des matières |
|
1 La classe Class
La réflexion est la capacité d'un programme à manipuler, en tant que données, les entités qui représentent l'état du programme pendant sa propre exécution. On distingue :
La classe Class est une «méta-classe».
Les instances de la classe Class représentent les classes et les interfaces des objets utilisés dans une application ( y compris les tableaux ).
La création d'une instance de la classe Class se fait à la première création d'une instance de la classe, ou à l'appel de la méthode de classe de Class, forName(String nom) qui retourne une référence à l'instance de classe, en chargeant la classe si elle n'est pas déjà chargée.
Toute instance de classe peut accéder à l'instance de sa classe par la méthode getClass().
Supposons définies les classes suivantes :
class A { static{ System.out.println(" chargement de A ");} } class B extends A{ static{ System.out.println(" chargement de B ");} } class C { static{ System.out.println("chargement de C ");} }
Alors les instructions suivantes :
A a = new A(); B b = new B(); try { Class c = Class.forName("C"); }catch(ClassNotFoundException cnfe){ System.out.println(" classe pas trouvée : "+cnfe.getMessage() ) }
Provoquent les sorties :
chargement de A chargement de B chargement de C
2 Obtenir une référence à l'instance de Class
Class cA1 = A.class ;
Class cA2 = Class.forName("A");
A a = new A() ; Class cA = a.getClass() ;
class A<T, V>{
// ...
}
A <String, Integer> a = new A<String, Integer> () ;
Class<? extends A> cA = a.getClass() ;
3 La méthode getName()
La méthode getName() retourne le nom de la classe. Ce nom est construit de la façon suivante pour les tableaux :
Object[][] to = new Object[1][2]; Object o = new Object(); int [] ti = {1, 2, 3}; System.out.println(to.getClass().getName()); System.out.println(o.getClass().getName()); System.out.println(ti.getClass().getName()); |
[[Ljava.lang.Object; java.lang.Object [I |
Les méthodes de la classe Class permettent de connaître :
Exemple :
classA <T extends Integer, V> implements Comparable<T> { public T aDeA; public A(){} public void fDeA(){} public int compareTo(T o) { return 0; } } class B<T extends Integer, V> extends A<T, V> implements Cloneable, Comparable<T>{ public int aDeB; private int prive; public B(Integer a) { aDeB = a; } public B(){} public String toString(){ return "B : "+aDeB; } public void setADeB(T d) { aDeB = d; } public void fDeB(){} }
Le code suivant :
B b = new B(); Class cB = b.getClass(); System.out.println(" les attributs de : "+ cB.getName()); Field fs[] = cB.getFields(); if( fs.length!=0) for( int i = 0; i < fs.length; ++i){ tem.out.println(fs[i]); } else System.out.println(" pas d'attributs"); System.out.println(" les méthodes de : "+ cB.getName()); Method ms[] = cB.getMethods(); if( ms.length!=0) for( int i = 0; i < ms.length; ++i){ System.out.println(ms[i]); } else System.out.println(" pas de méthode"); System.out.println(" les constructeurs de : "+ cB.getName()); Constructor cs[] = cB.getConstructors(); if ( cs.length!=0) for( int i = 0; i < cs.length; ++i){ System.out.println(cs[i]); } else System.out.println(" pas de constructeur"); System.out.println(" les interfaces de : "+ cB.getName()); Class is[] = cB.getInterfaces(); if( is.length!=0) for ( int i = 0; i < is.length; ++i){ System.out.println(is[i]); } else System.out.println(" pas d'interface"); System.out.println(" nom de la classe mère : "+cB.getSuperclass().getName()); Type ts = cB.getGenericSuperclass(); System.out.println(" nom de la classe mère générique : "+ts.toString()); Type[] tis = cB.getGenericInterfaces(); System.out.println(" nom des interfaces génériques implémentées : "); for( int i = 0; i < tis.length; ++i) System.out.println(" "+tis[i]);
Donne les sorties suivantes :
les attributs de : B public int B.aDeB public java.lang.Integer A.aDeA les méthodes de : B public void B.setADeB(java.lang.Integer) public void B.fDeB() public java.lang.String B.toString() public void A.fDeA() public static void A.main(java.lang.String[]) public int A.compareTo(java.lang.Integer) public int A.compareTo(java.lang.Object) public final void java.lang.Object.wait() throws java.lang.InterruptedException public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException public native int java.lang.Object.hashCode() public final native java.lang.Class java.lang.Object.getClass() public boolean java.lang.Object.equals(java.lang.Object) public final native void java.lang.Object.notify() public final native void java.lang.Object.notifyAll() les constructeurs de : B public B(java.lang.Integer) les interfaces de : B interface java.lang.Cloneable interface java.lang.Comparable nom de la classe mère : A nom de la classe mère générique : A<T, V> nom des interfaces génériques implémentées : interface java.lang.Cloneable java.lang.Comparable<T>
5 Aller plus loin ...
5.1 Création d'instance
On peut créer une instance d'une classe, en ne connaissant que son nom :
try{ Class<?> cB = Class.forName ("B"); // Récupération du constructeur prenant en paramètre un Integer Class<?> ci = Class.forName ("java.lang.Integer"); Class [] parametres = { ci }; Constructor constructeur = cB.getConstructor (parametres); // Création d'un objet de la classe B Object o = constructeur.newInstance (new Object [] {12}); System.out.println(o); }catch (ClassNotFoundException e){ System.out.println(" La classe "+e.getMessage()+" n'existe pas"); }catch (NoSuchMethodException e){ System.out.println("Le constructeur "+e.getMessage()+" n'existe pas"); }catch (InstantiationException e){ System.out.println("La classe est abstraite ou est une interface "); }catch (IllegalAccessException e){ System.out.println("La classe n'est pas accessible"); }catch (java.lang.reflect.InvocationTargetException e){ System.out.println(e.getMessage()); }
5.2 Invocation de méthode
Le code suivant permet d'appeler la méthode setADeB et la méthode toString pour l'objet o créé précédemment :
// appel de setADeB Class [] typeParametre = {Integer.class}; Object[] parametre = {15}; Method m = cB.getMethod("setADeB", typeParametre); m.invoke(o, parametre); // appel de toString m = cB.getMethod("toString", (Class<?>[])null); System.out.println(m.invoke(o, (Object[])null));
5.3 Modification d'un attribut privé
try {
// getDeclaradField pour obtenir un attribut privé
Field f = cB.getDeclaredField("prive");
f.setAccessible(true);
System.out.println("prive avant modification : "+f.getInt(o));
f.setInt(o, 123);
System.out.println("prive après modification : "+f.getInt(o));
} catch (SecurityException e) {
} catch (NoSuchFieldException e) {
}
5.4 Programmation de la commande javap
La commande javap permet d'afficher les informations contenues dans les fichiers de classes. Quelques unes des options sont :
Le code suivant permet de simuler la commande javap avec la seule option -private
public class Javap { public static String modificateurs(int mod) { String res = ""; if (Modifier.isPublic(mod)) res += " public"; if (Modifier.isPrivate(mod)) res += " private"; if (Modifier.isProtected(mod)) res += " protected"; if (Modifier.isStatic(mod)) res += " static"; if (Modifier.isAbstract(mod)) res += " abstract"; if (Modifier.isFinal(mod)) res += " final"; if (Modifier.isNative(mod)) res += " native"; if (Modifier.isTransient(mod)) res += " transient"; if (Modifier.isSynchronized(mod))res += " synchronized"; return res.substring(1); }
public static void main(String[] args) { if (args.length == 0) { System.out.println("pas d'arguments ..."); return; } for (int k = 0; k < args.length; ++k) { String nom = args[k]; try { Class cl = Class.forName(nom); // les modifieurs de la classe String res = modificateurs(cl.getModifiers()) + " class "+ cl.getName(); // la super classe res += " extends " + cl.getSuperclass().getName(); // les interfaces implémentées Class is[] = cl.getInterfaces(); if (is.length != 0) { res += " implements " + is[0].getName(); for (int i = 1; i < is.length; ++i) res += ", " + is[i].getName(); } res += "{\n"; // les attributs Field fs[] = cl.getDeclaredFields(); if (fs.length != 0) for (int i = 0; i < fs.length; ++i) res += " " + modificateurs(fs[i].getModifiers()) + " " + fs[i].getType() + " " + fs[i].getName()+ ";\n"; // les constructeurs Constructor cs[] = cl.getDeclaredConstructors(); if (cs.length != 0) for (int i = 0; i < cs.length; ++i) { res += " " + modificateurs(cs[i].getModifiers()) + " " + cs[i].getName() + "("; Class<?>[] params = cs[i].getParameterTypes(); if (params.length != 0) { res += params[0].getName(); for (int j = 1; j < params.length; ++j) res += ", " + params[j].getName(); } res += ");\n"; } // les méthodes Method ms[] = cl.getDeclaredMethods(); if (ms.length != 0) for (int i = 0; i < ms.length; ++i) { res += " " + modificateurs(ms[i].getModifiers()) + " " + ms[i].getReturnType() + " " + ms[i].getName() + "("; Class<?>[] params = ms[i].getParameterTypes(); if (params.length != 0) { res += params[0].getName(); for (int j = 1; j < params.length; ++j) res += ", " + params[j].getName(); } res += ");\n"; } res += "}"; System.out.println(res); } catch (ClassNotFoundException e) { System.out.println("La classe " + nom + " n'existe pas !"); } } } }