vendredi 23 avril 2010

Métaprogrammation et introspection en JAVA

La métaprogrammation au sein d'un langage pseudo-compilé ou comilié est très difficile et surtout d'une utilité limitée. En revanche l'introspection est un moyen pour approfondir ses connaissances d'un langage.

En java la classe : java.lang.reflect permet d'obtenir des informations intéressantes. Cette classe utilisée avec l'utilitaire 'javap' (livré avec le jdk) seront de bons compagnons de jeux:

Reflec liste les méthodes d'une classe , les attributs publics , les constructeurs et aussi la classe Mère.

Ici un exemple d'utilisation :



import java.lang.reflect.*;
abstract class mammifere {
public String nom;
mammifere(String s){
nom = s;
}


abstract void parle();
void quiSuisJe(){
System.out.println( "--------------------------" );
Object o = this.getClass();
String s = o.toString();
s = s.substring(6);
System.out.println( " Je suis un " + s );
}
void jeSaisFaire() {
Object o = this.getClass();
String s = o.toString();
s = s.substring(6);
try {
Class c = Class.forName(s);

Method m[] = c.getDeclaredMethods();
for (int i = 0; i < m.length; i++)
{
System.out.println("je sais faire :" + m[i].toString());
}
}
catch (Throwable e) {
System.err.println(e);
}
}
void mesQualites() {
Object o = this.getClass();
String s = o.toString();
s = s.substring(6);
try {
Class c = Class.forName(s);

Field f[] = c.getFields();

for (int i = 0; i < f.length; i++)
{
System.out.println("Mes qualites sont :" + f[i].toString());
}
}
catch (Throwable e) {
System.err.println(e);
}
}

}
class Humain extends mammifere {
Humain( String s ){
super( s );
}
void parle(){
quiSuisJe();
System.out.println( "Bonjour je m'appelle " + nom +
" et je deteste la java !!" );
System.out.println("");
}
}

class Chien extends mammifere {
public String race ;
Chien( String s ){
super( s );
}
void parle(){
quiSuisJe();
System.out.println( "OUAF OUAF OUAF je m'appelle " + nom +
" et je ronge mon frein !! non !! mon os ..." );
System.out.println("");
}
void FaireLeBeau(){
System.out.println("sur deux pates");
}
}

class Chat extends mammifere {
Chat( String s ){
super( s );
}
void parle(){
quiSuisJe();
System.out.println( "MIAOUUUUUUUU je m'appelle " + nom +
" et je ronronne un max ..." );
System.out.println("");
}
}

class mam {
public static void main(String args[]){
mammifere mams[] = new mammifere[ 3 ];
mams[0] = new Humain( "Jean Valjean" );
mams[1] = new Chat( "O'Mallet" );
mams[2] = new Chien( "Droopy" );

for(int i=0; i<3; i++){
mams[ i ].parle();
mams[ i].jeSaisFaire();
mams[ i].mesQualites();

}
}
}

Avec des exemples de resultats.



je sais faire :void Chien.parle()
je sais faire :void Chien.FaireLeBeau()
Mes qualites sont :public java.lang.String Chien.race
Mes qualites sont :public java.lang.String mammifere.nom




La méthode GetMethods retourne les méthodes 'friendly' ,en revanche getFields ne fonctionne que sur les attributs explicitement publics.


Le programme javap est un décompilateur
Il s'utilise comme ceci :
javap <>


ex: javap Chien

Avec le résultat suivant:

javap Chien
Compiled from "mam.java"
class Chien extends mammifere{
Chien(java.lang.String);
void parle();
void FaireLeBeau();
}


Tout cela reste bien triste en raison de l'aspect statique de JAVA.


Ici un article complet sur le sujet.

Aucun commentaire: