IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

avec Java Discussion :

appel méthode réflexion


Sujet :

avec Java

  1. #1
    Membre éprouvé
    Inscrit en
    Avril 2006
    Messages
    853
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 853
    Points : 929
    Points
    929
    Par défaut appel méthode réflexion
    salut

    j'ai pris l'exemple du site à propos du lancement d'une méthode avec la réfection

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
     
    import java.lang.reflect.Method;
     
    public class Test {
     
        public Test() {
        }
     
        public int allo(int x) {
            System.out.println(x);
            return x;
        }
     
        public Object lancerMethode(Object obj, Object[] args, String nomMethode) throws Exception {
            Class[] paramTypes = null;
            if (args != null) {
                paramTypes = new Class[args.length];
                for (int i = 0; i < args.length; ++i) {
                    paramTypes[i] = args[i].getClass();
                }
            }
            Method m = obj.getClass().getMethod(nomMethode, paramTypes);
            return m.invoke(obj, args);
        }
     
        public static void main(String[] args) throws Exception {
            Test t = new Test();
    		Object parametres[] = { new Integer(-1) };
     
            t.lancerMethode(new Test(), parametres , "allo");
        }
    }
    j'arrive toujours pas à lancer la méthode de ma classe Test... une idée?

    merci

  2. #2
    Membre éclairé Avatar de zorm
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    584
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Décembre 2004
    Messages : 584
    Points : 672
    Points
    672
    Par défaut
    La méthode allo n'est pas appelé à cause du type de son attribut. int et Integer, c'est pas la même chose.

    essayes avec ça:
    ou ça:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
        public int allo(int x) {
            System.out.println(x);
            return x;
        }
     
        public int allo(Integer x) {
            return allo(x.intValue());
        }

  3. #3
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Salut,

    Citation Envoyé par zorm Voir le message
    La méthode allo n'est pas appelé à cause du type de son attribut. int et Integer, c'est pas la même chose.
    Pas tout à fait...
    Lorsqu'on a un attribut de type primitif (comme int), on doit bien utiliser le type wrapper correspondant (Integer) si on veut utiliser l'API de reflection.

    Le problème ici c'est que tu détermines les paramètres de la méthode selon le type des paramètres. Or getMethod() a besoin des types précis tandis que invoke() ne nécessite que des types compatibles.

    Exemple, pour une methode du style :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    public void method(int a, Object b, Number n);
    getMethod() doit recevoir exactement les types suivants :
    1. int.class
    2. Object.class
    3. Number.class


    Par contre invoke() attend :
    1. Un objet de type Integer pour le convertir en int.
    2. N'importe quel instance d'objet dont le type est un fils de Object, c'est à dire n'importe quel objet puisque tout hérite de Object !
    3. N'importe quel instance d'objet dont le type est un fils de Number. Cela pourrait être Integer, Double, Float...




    Il y a moyen de faire ce que tu veux, mais il faut parcourir la liste des méthodes pour retrouver une méthode avec une liste de paramètre "compatible", ce qui donne (syntaxe Java 5.0) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    	/**
             * Indique si l'instance 'argValue' est compatible avec 'argType'.
             * C'est à dire :
             * 
             *  Si 'argType' est un type primitif, 'argValue' doit être du type
             *  correspondant (int - Integer...).
             *  
             *  Si 'argType' est un type standard, 'argValue' peut être null
             *  ou bien correspondre à un type fils.
             * @param argType Le type à vérifier
             * @param argValue L'instance qui doit correspondre au type
             * @return true si l'instance est compatible / false sinon.
             */
    	private static boolean isCompatible(Class<?> argType, Object argValue) {
     
    		if (argType.isPrimitive()) {
    			// On a affaire à un type primitif :
    			// On refuse les valeurs null
    			if (argValue==null) return false;
    			// Et n doit vérifier que 'argValue' correspondent au type wrapper
    			if (argType==byte.class) return argValue.getClass()==Byte.class;
    			if (argType==boolean.class) return argValue.getClass()==Boolean.class;
    			if (argType==char.class) return argValue.getClass()==Character.class;
    			if (argType==short.class) return argValue.getClass()==Short.class;
    			if (argType==int.class) return argValue.getClass()==Integer.class;
    			if (argType==long.class) return argValue.getClass()==Long.class;
    			if (argType==float.class) return argValue.getClass()==Float.class;
    			if (argType==double.class) return argValue.getClass()==Double.class;
    			// Sinon on retourne false (on ne devrait pas arriver ici)
    			return false;
    		} else {
    			// On a affaire à un type quelquonque :
    			// On accepte soit null, soit une valeur de même instance :
    			return argValue==null || argType.isInstance(argValue);
    		}
    	}
     
    	/**
             * Invoque une méthode sur une instance, en utilisants le type des paramètres
             * pour retrouver la bonne méthode.
             * @param instance L'instance de l'objet
             * @param methodName Le nom de la méthode
             * @param args La liste des paramètres
             * @return Le retour de la méthode, 
             * @throws NoSuchMethodException
             * @throws IllegalArgumentException
             * @throws IllegalAccessException
             * @throws InvocationTargetException
             */
    	public static Object invoke(final Object instance, final String methodName, final Object...args)
    	throws NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
     
    		final Class<?> clazz = instance.getClass();
    		// On parcours le tableau des méthodes :
    		for (final Method method : clazz.getMethods()) {
    			// Si le nom de la méthode correspond :
    			if (method.getName().equals(methodName)) {
    				Class<?>[] argsType = method.getParameterTypes();
    				// Et que le nombre de paramètres est identique :
    				if (argsType.length==args.length) {
    					boolean ok = true;
    					// On vérifie le type de chaques paramètres :
    					for (int i=0; i<argsType.length; i++) {
    						ok = ok && isCompatible(argsType[i], args[i]);
    					}
    					// Si tout est OK on execute la 
    					if (ok) {
    						return method.invoke(instance, args);
    					}
    				}
    			}
    		}
    		// Sinon on génère une exception avec un message de la forme 'NomClasse.nomMethode(argsType)'
    		StringBuilder sb = new StringBuilder(clazz.getName());
    		sb.append(".").append(methodName).append("(");
    		for(Object obj : args) {
    			sb.append(obj==null?"null":obj.getClass().getName());
    			sb.append(", ");
    		}
    		sb.delete(sb.length()-2, sb.length());
    		sb.append(")");
    		throw new NoSuchMethodException(sb.toString());
    	}
    Ce qui te donnerait dans ton cas :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    invoke (t, "allo", -1);
    Attention toutefois, car s'il y a plusieurs méthodes "compatibles" seule la première trouvé sera appelée...




    a++

  4. #4
    Membre éprouvé
    Inscrit en
    Avril 2006
    Messages
    853
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 853
    Points : 929
    Points
    929
    Par défaut
    Citation Envoyé par adiGuba Voir le message
    Salut,


    Pas tout à fait...
    Lorsqu'on a un attribut de type primitif (comme int), on doit bien utiliser le type wrapper correspondant (Integer) si on veut utiliser l'API de reflection.
    je sais c'est pour ça que j'ai employer Integer...

    alors quel est la façon d'appeler ma méthode allo à avec

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    public Object lancerMethode(Object obj, Object[] args, String nomMethode)

  5. #5
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par robert_trudel Voir le message
    alors quel est la façon d'appeler ma méthode allo à avec

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    public Object lancerMethode(Object obj, Object[] args, String nomMethode)
    Soit tu utilises ma méthode, soit tu passes en plus les types précis des paramètres de la méthode, donc dans ton cas un tableau de Class contenant un int.class :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
        public Object lancerMethode(Object obj, Class[] paramTypes, Object[] args, String nomMethode) throws Exception {
            Method m = obj.getClass().getMethod(nomMethode, paramTypes);
            return m.invoke(obj, args);
        }

    a++

  6. #6
    Membre éprouvé
    Inscrit en
    Avril 2006
    Messages
    853
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 853
    Points : 929
    Points
    929
    Par défaut
    Citation Envoyé par adiGuba Voir le message
    Soit tu utilises ma méthode, soit tu passes en plus les types précis des paramètres de la méthode, donc dans ton cas un tableau de Class contenant un int.class :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
        public Object lancerMethode(Object obj, Class[] paramTypes, Object[] args, String nomMethode) throws Exception {
            Method m = obj.getClass().getMethod(nomMethode, paramTypes);
            return m.invoke(obj, args);
        }

    a++
    alors la méthode prise de la faq.. ne fonctionne pas vraiment ? ou bien faudrait un exemple avec cette méthode et son utilisation...

  7. #7
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par robert_trudel Voir le message
    alors la méthode prise de la faq.. ne fonctionne pas vraiment ? ou bien faudrait un exemple avec cette méthode et son utilisation...
    Je n'avais pas vu que cela venait de la FAQ...
    Cette méthode ne peut fonctionner que dans le cas où les types des paramètres sont strictement identiques à ceux déclarées dans la méthode...

    Ce qui est impossible si on utilise un type primitif ou une interface, et dépend fortement du contexte pour les autres cas (en clair cela ne marche que si on passe le type exact et pas un type fils).


    J'ai soumis une demande de modif dans le thread de la FAQ pour signaler cela


    a++

Discussions similaires

  1. Réponses: 8
    Dernier message: 19/07/2007, 12h15
  2. JSP Appel méthode JAVA
    Par maxime17s dans le forum Servlets/JSP
    Réponses: 9
    Dernier message: 04/06/2007, 11h59
  3. appel méthode d'une dll
    Par spilmann dans le forum Servlets/JSP
    Réponses: 1
    Dernier message: 14/02/2007, 11h47
  4. Appel Méthode 4D par Javascript
    Par mxh77 dans le forum 4D
    Réponses: 2
    Dernier message: 02/10/2006, 14h48
  5. Débutante - Pb appel méthode static
    Par nmetais dans le forum Langage
    Réponses: 2
    Dernier message: 23/09/2005, 17h23

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo