Christophe Jacquet, Associate Professor at Supélec

Enseignement > Exemples en Java >

Création d'une instance d'une classe dont on connaît le nom

Il arrive que l'on connaisse le nom d'une classe, sous forme d'une chaîne de caractères, et que l'on ait envie de l'instancier. Par exemple, si l'on écrit un logiciel de retouche photo, on peut laisser à des personnes tierces la possibilité de créer des filtres supplémentaires. Au lancement, le logiciel inspecte alors un répertoire bien particulier à la recherche de fichiers de classes sensées correspondre à des filtres supplémentaires. À partir du nom des classes ainsi récupérés, il s'agit donc d'instancier les classes.

/* ############################################################################
 * 
 * Instanciation.java : démonstration de l'instanciation de classes Java
 *                      dont on connaît le nom exprimé sous forme de chaînes
 *                      de caractères.
 * 
 * Auteur : Christophe Jacquet, Supélec
 * 
 * Historique
 * 2006-11-27  Création
 * 
 * ############################################################################
 */

import java.awt.Color;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/** 
 * Interface d'un filtre à appliquer à des pixels colorés.
 * 
 * Un filtre rend une couleur correspondant à l'opération de filtration, avec
 * une transparence fixée au moment de la construction du filtre.
 * 
 * Chaque filtre doit donc posséder un constructeur qui prend en paramètre une
 * valeur "int" de transparence.
 */
interface Filtre {
	/**
	 * Effectue le filtrage d'un pixel
	 * @param c la couleur du pixel avant filtrage
	 * @return la couleur après application du filtre
	 */
	public Color filtrer(Color c);
}

/** Extrait la composante verte des couleurs */
class CoucheVerte implements Filtre {
	private int alpha_;
	
	public CoucheVerte(int alpha) {
		alpha_ = alpha;
	}
	
	public Color filtrer(Color c) {
		return new Color(0, c.getGreen(), 0, alpha_);
	}
}

/** Transforme les couleurs en niveaux de gris */
class Gris implements Filtre {
	private int alpha_;
	
	public Gris(int alpha) {
		alpha_ = alpha;
	}
	
	public Color filtrer(Color c) {
		float r = c.getRed()/255f, v = c.getGreen()/255f, b = c.getBlue()/255f;
		float gris = 0.299f * r + 0.587f * v + 0.114f * b;
		return new Color(gris, gris, gris, alpha_/255f);
	}
}

public class Instanciation {
	// indique les classes des paramètres du constructeur d'un filtre. Il y a
	// un seul paramètre, de type "int"
	// NB: s'il s'agissait de la *classe* Integer, il faudrait écrire
	//     "Integer.class", et de même pour tout type objet.
	private static final Class[] sigConstructeurFiltre = {Integer.TYPE};
	
	private static Filtre instancieFiltre(String nom, int alpha) {
		Class classeDuFiltre = null;  // représentation de la classe du filtre
		
		// essaie d'obtenir un objet de type Class qui représente la classe
		// de nom "nom"
		try {
			classeDuFiltre = Class.forName(nom);
		} catch(ClassNotFoundException e) {
			// au cas où la classe n'existe pas...
			System.err.println("Classe " + nom + " non trouvée.");
			System.exit(1);
		}
		
		Constructor constructeurFiltre = null;  // représente le constructeur
		                                        // souhaité pour le filtre
		
		// essaie d'obtenir un objet de type Constructor qui représente le
		// constructeur de la classe de nom "nom", dont la signature est
		// donnée par le tableau paramsConstructeurFiltre
		try {
			constructeurFiltre = 
				classeDuFiltre.getConstructor(sigConstructeurFiltre);
		} catch(NoSuchMethodException e) {
			// au cas où il n'y a pas de co
			System.err.println("Pas de constructeur avec la signature donnée.");
			System.exit(1);
		}
		
		// paramètres du constructeur : ici transparence fournie en paramètre
		// à cette méthode-ci
		Object params[] = {alpha};
		
		try {
			return (Filtre)constructeurFiltre.newInstance(params);
		} catch(InstantiationException e) {
			System.err.println("Classe non instanciable.");
			System.exit(1);
		} catch (IllegalArgumentException e) {
			System.err.println("Mauvais nombre ou type d'arguments.");
			System.exit(1);
		} catch (IllegalAccessException e) {
			System.err.println("Constructeur inaccessible.");
			System.exit(1);
		} catch (InvocationTargetException e) {
			System.err.println("Exception levée par le constructeur.");
			System.exit(1);
		}
		
		return null;
	}
	
	
	private final static String filtresATester[] = 
								{"CoucheVerte", "Gris", "Truc"};
	
	public static void main(String[] args) {
		Color c = new Color(100, 150, 190);
		System.out.println("Couleur de départ: " + c);
		
		for(String filtreATester : filtresATester) {
			// construit un filtre correspondant au nom "filtreATester", et
			// avec une transparence fixée à 0.7
			Filtre leFiltre = instancieFiltre(filtreATester, 67);
			
			System.out.println("Filtrage par " + filtreATester + " : " + 
					leFiltre.filtrer(c));
		}
	}
}