web-dev-qa-db-fra.com

Java: NoSuchMethodException lorsque la méthode existe clairement

Sur mon projet actuel, j'ai ressenti le besoin de créer une sorte de système de rappel simulé en Java utilisant la réflexion. Cependant, j'ai des problèmes pour que ma réflexion fonctionne réellement. Le code à la faute suit:

public Callback(Object parentObj, String methodName, Class<?>...parameters)
{
    if(parentObj == null)
        throw new IllegalArgumentException("parentObj cannot be null", new NullPointerException());

    Class<?> clazz = parentObj.getClass();

    // Trace debugging, see output
    for(Method m : clazz.getDeclaredMethods())
        if(m.getName().equals("myMethod")) System.out.println (m);

    try { this.method = clazz.getMethod(methodName, parameters); }
    catch(NoSuchMethodException nsme) { nsme.printStackTrace(); } // Exception caught
    catch(SecurityException se) { se.printStackTrace(); }

    this.parentObj = parentObj;
    this.parameters = parameters;
}

Lorsque je construis l'objet Callback, j'utilise une syntaxe comme celle-ci:

new Callback(this, "myMethod", boolean.class)

Lorsque j'essaie de créer mon pseudo-rappel, il frappe le bloc catch NoSuchMethodException. J'ai inclus un débogage de trace ci-dessus pour montrer la sortie d'une de mes méthodes qui échoue. Le résultat:

private void my.package.MyClass.myMethod(boolean)
Java.lang.NoSuchMethodException: my.package.MyClass.myMethod(boolean)
    at Java.lang.Class.getMethod(Class.Java:1605)
    at my.package.other.Callback.<init>(Callback.Java:63)

Je ne pouvais pas comprendre le problème, alors j'ai commencé à chasser, en vain. Le mieux que j'ai pu trouver était la mention d'un conflit de version entre le JAR compilé et le runtime. Cependant, MyJar.jar/META-INF/MANIFEST.MF Contient Created-By: 1.6.0_02 (Sun Microsystems Inc.). Mon IDE exécute C:\Program Files\Java\jdk1.6.0_02\bin\javac.exe Pour compiler mon projet. J'utilise C:\Program Files\Java\jdk1.6.0_02\bin\Java.exe Pour exécuter mon JAR.

Je ne comprends pas pourquoi Class.getMethod Prétend que la méthode n'existe pas, mais Class.getMethods Ne semble avoir aucun problème à la trouver. Aidez-moi? :(

36
Brian S

Votre méthode est privée mais getMethod() ne renvoie que la méthode publique.

Vous devez utiliser getDeclaredMethod().

104
ZZ Coder

Le Javadoc pour getMethod n'est pas explicite, mais il semble qu'il puisse lever une NoSuchMethodException pour les méthodes qui ne sont pas publiques, et votre méthode est privée.

5
Adam Crume

Vous devez que la liste de paramètres soit absolument correcte pour la méthode que vous souhaitez pour que l'appel réussisse.

J'ai trouvé que de minuscules étapes sont importantes lors de la réflexion car le compilateur n'aide pas. Écrivez un petit extrait qui invoque en fait exactement la méthode que vous voulez dans this cas particulier, puis quand cela fonctionne, généralisez-le dans le cadre ici. Je me concentrerais sur les paramètres passés.

Le problème de versionnage qui peut provoquer NoSuchMethodException n'est pas une différence entre les versions du compilateur. C'est une différence dans la version de (dans votre cas) MyClass au moment de la compilation par rapport à l'exécution.

Étant donné que vous utilisez la réflexion, votre problème peut n'avoir rien à voir avec le contrôle de version. Cela n'expliquerait certainement pas un comportement différent entre getMethod et getDeclaredMethods, car vous les exécutez sur la même instance de classe, donc une différence de version n'est pas vraiment possible.

Êtes-vous sûr que les paramètres correspondent à votre méthode actuelle?

0
Laurence Gonsalves