Instanciation d'une classe dont le nom est dans une variable

Résolu
sphaxslayer Messages postés 216 Date d'inscription mardi 5 avril 2005 Statut Membre Dernière intervention 17 septembre 2008 - 16 janv. 2008 à 10:02
sphaxslayer Messages postés 216 Date d'inscription mardi 5 avril 2005 Statut Membre Dernière intervention 17 septembre 2008 - 16 janv. 2008 à 13:26
Bonjour tout le monde,

voilà j'ai un petit souci qui est en fait je pense la question la plus tordue du monde entier et de l'univers. J'ai un système d'héritage de classes Filtres. Chaque nom de classe (et donc du fichier .java...) est enregistré en base et donc récupérable. Ces "filtres" sont sélectionnés et on construit un ArrayList de leur noms en fonction de ceux qu'on a sélectionnés.

Ma question est la suivante : est-il possible de déclarer une variable dont le type serait la valeur d'une autre. Exemple :

new (ArrLst.get(0)) filter1;
new (ArrLst.get(1)) filter2;
avec ArrLst.get(0) MathFilter , ArrLst.get(1) PunctuationFilter
et 2 classes existantes : MathFilter.java, PunctuationFilter.java

Merci d'avance... Bien qu'à mon avis, la réponse est claire :(

"Un seul Être vous manque, et tout est dépeuplé..."

4 réponses

Twinuts Messages postés 5375 Date d'inscription dimanche 4 mai 2003 Statut Modérateur Dernière intervention 14 juin 2023 111
16 janv. 2008 à 12:54
Salut,

en gros si je comprend bien tu veux créer une instance d'un objet sans passer par sa référence directe mais seulement par son nom.

Bah jusque là aucun problème en java c'est faisable. Pour ce faire tu dois utiliser le mécanisme de réflexion... voici deux solutions (les plus courantes) :
 1 – L'objet que tu veux instancier possède un constructeur vide (sans argtuments).
 2 – L'objet que tu veux instancier contient 1 ou plusieurs constructeurs avec argument.

solution 1 :
L'exemple ci-dessous montre comment instancier la classe java.util.Random (te suffit d'adapter pour ton code)

import java.lang.reflect.Method;

public class Test {

    public static void main(String[] args) {
        // Note : ce bout de code trapue toutes les exception, et ne fait pas de test sur la validité
        // des champs.
        // ATTENTION: l'utilisation de la réflexion alourdi le temps de traitement d'un code
        try {
            // Lorsque tu veux instancier un objet par son nom il te faut le nom complet
            // soit le nom de ton objet mais pas seulement, il te faut également
            // connaître l'emplacement de ta classe (dans quel package elle se trouve).
            String className = "java.util.Random";
            // la méthode forName(...) permet de demander à la JVM de trouver le byte code
            // associé à un objet Class, afin de pouvoir le manipuler ultérieurement.
            Class<?> classRandom = Class.forName(className);
            // Affichage de la classe.
            System.out.println(classRandom);
            // Demande à la JVM de trouver le constructeur vide de ton objet
            // afin de créer une instance dessus.
            Object objectRandom = classRandom.newInstance();
            // Affichage de l'instance sur l'objet Random.
            System.out.println(objectRandom);
            // Invocation d'une méthode afin de tester si tout ce passe comme prévu ^^.
            // La première étape consiste à trouver la méthode dans l'objet Random
            // pour le test nous allons nous intéresser à la méthode nextInt(int).
            Method nextInt = classRandom.getMethod(
                    "nextInt", // Nom de la méthode qui nous intéresse.
                    // Il faut ensuite indiquer le type des paramètres de la méthode
                    // en l'occurrence ici on choisi la méthode ayant un paramètre de type int.
                    new Class[] { int.class }
            );
            // Affichage de la méthode
            System.out.println(nextInt);
            // Maintenant il suffit d'invoquer la méthode en question et de traiter le résultat.
            Object result = nextInt.invoke(
                    objectRandom, // Référence sur l'objet propriétaire de la méthode.
                    // Il faut ensuite indiquer la valeur des paramètres de la méthode
                    // en l'occurrence ici on a choisi la méthode ayant un paramètre de type int
                    // donc on lui met une valeur... par exemple... "50".
                    new Object[] { 50 }
            );
            // Exploitation du retour de la méthode (nextInt retourne un entier).
            int value = (Integer)result;
            // Affichage de la valeur
            System.out.println(value);
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
}

solution 2:
L'exemple ci-dessous montre comment instancier la classe java.io.File (te suffit d'adapter pour ton code)
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public class Test {

    public static void main(String[] args) {
        // Note : ce bout de code trappe toutes les exception, et ne fait pas de test sur la validité
        // des champs.
        // ATTENTION: l'utilisation de la réflexion alourdi le temps de traitement d'un code
        try {
            // Lorsque tu veux instancier un objet par son nom il te faut le nom complet
            // soit le nom de ton objet mais pas seulement, il te faut également
            // connaître l'emplacement de ta classe (dans quel package elle se trouve).
            String className = "java.io.File";
            // la méthode forName(...) permet de demander à la JVM de trouver le byte code
            // associé à un objet Class, afin de pouvoir le manipuler ultérieurement.
            Class<?> classFile = Class.forName(className);
            // Affichage de la classe.
            System.out.println(classFile);
            // Maintenant il faut spécifier le type de constructeur à utiliser afin de créer une instance de la classe File
            // Pour ce faire, on utilise l'objet Constructor du package reflect.
            // L'instance de l'objet Constructor ce fait par l'intermediaire de la méthode getConstructor en spécifiant le constructeur
            // de notre choix, soit ici celui qui prend en paramètre un String
            Constructor<?> constructorFile = classFile.getConstructor(new Class[] {String.class});
            // Affichage de l'instance sur l'objet Constructor de la classe File.
            System.out.println(constructorFile);
            // Demande à la JVM de trouver le constructeur prenant en paramètre un String
            // afin de créer une instance dessus.
            Object objectFile = constructorFile.newInstance(new Object[] { "./fichier.txt" }); // on passe en paramètre le nom d'un fichier pour que la classe File se cale dessus ^^
            // Affichage de l'instance sur l'objet File.
            System.out.println(objectFile);
            // Invocation d'une méthode afin de tester si tout ce passe comme prévu ^^.
            // La première étape consiste à trouver la méthode dans l'objet File
            // pour le test nous allons nous intéresser à la méthode exists().
            Method exists = classFile.getMethod(
                    "exists", // Nom de la méthode qui nous intéresse.
                    // Il faut ensuite indiquer le type des paramètres de la méthode
                    // en l'occurrence ici on choisi la méthode n'ayant aucun paramètre.
                    new Class[] {}
            );
            // Affichage de la méthode
            System.out.println(exists);
            // Maintenant il suffit d'invoquer la méthode en question et de traiter le résultat.
            Object result = exists.invoke(
                    objectFile, // Référence sur l'objet propriétaire de la méthode.
                    // Il faut ensuite indiquer la valeur des paramètres de la méthode
                    // en l'occurrence ici on a choisi la méthode n'ayant aucun paramètre.
                    new Object[] {}
            );
            // Exploitation du retour de la méthode (exists retourne un boolean).
            boolean value = (Boolean)result;
            // Affichage de la valeur
            System.out.println(value);
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
}

------------------------------------
"On n'est pas au resto : ici on ne fait pas dans les plats tout cuits ..."

OoWORAoO
3
KenZara Messages postés 112 Date d'inscription vendredi 24 décembre 2004 Statut Membre Dernière intervention 20 décembre 2011
16 janv. 2008 à 11:56
    Bonjour,

A mon avis ce que tu cherches à faire n'est pas possible :/ .... Mais détaille nous un peu plus, il se peut que j'ai mal compris ce que tu veux faire.
En tout cas faire ça: ArrLst.get(0) == MathFilter sachant que le MathFilter est le nom de la classe, hum je ne pense pas...

Voilou ... Sinon j'adore ton message de fin :) ...

Kenza
0
sphaxslayer Messages postés 216 Date d'inscription mardi 5 avril 2005 Statut Membre Dernière intervention 17 septembre 2008
16 janv. 2008 à 13:20
Salut,
et merci de ta réponse.. Effectivement tu as bien compris à mon avis, j'aurais voulu pouvoir instancier un objet d'un type donné par la valeur d'une variable, c'est bien ça... Tant pis, en "bricolage" j'ai fait un bloc de if..else if... laid pas beau (pour l'instant j'ai que 3 classes de filtres, mais dans un temps t à venir, il se pourrait qu'il y en ait une petite dizaine par exemple...)

... ahh... si le switch marchait sur les chaînes de caractères en Java...

Quant à ma signature, il s'agit d'une citation d'Alphonse de Lamartine, parodié d'ailleur par Woodie Allen en "Un seul être vous manque et c'est justement celui qui vous doit de l'argent" ou quelque chose du genre :-)

Merci en tous cas, de confirmer ma supposition... J'ai feinté pour le moment, je pense que le système général de nos classes est à reprendre mais bon...

"Un seul Être vous manque, et tout est dépeuplé..."
0
sphaxslayer Messages postés 216 Date d'inscription mardi 5 avril 2005 Statut Membre Dernière intervention 17 septembre 2008
16 janv. 2008 à 13:26
Ah, j'avais pas actualisé la page, merci pour ton exemple complet et détaillé Twinuts, ca me parait convenir, je vais tester ça : j'ignorais totalement l'existence d'un Class<?> ... ce qui tombe plutôt bien je dirais :-)

"Un seul Être vous manque, et tout est dépeuplé..."
0
Rejoignez-nous