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 en utilisant la réflexion. Cependant, j'ai des problèmes pour que ma réflexion fonctionne réellement. Le code en 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;
}
Quand je construis l'objet Callback
, j'utilise la syntaxe comme ceci:
new Callback(this, "myMethod", boolean.class)
Lorsque j'essaie de créer mon pseudo rappel, il frappe le NoSuchMethodException
bloc catch. J'ai inclus un débogage de trace ci-dessus pour montrer la sortie de l'une de mes méthodes échouant. Le sortie:
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 n'arrivais pas à comprendre le problème, alors j'ai commencé à chasser, en vain. Le mieux que j'ai pu trouver était la mention du 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 est en cours d'exécution C:Program FilesJavajdk1.6.0_02binjavac.exe
pour compiler mon projet. J'utilise C:Program FilesJavajdk1.6.0_02binjava.exe
pour exécuter mon pot.
Je ne comprends pas pourquoi Class.getMethod
prétend que la méthode n'existe pas, mais Class.getMethods
semble ne pas avoir de problème à la trouver. De l'aide? :(
4 réponses
Votre méthode est privée mais getMethod()
ne renvoie que la méthode publique.
Vous devez utiliser getDeclaredMethod()
.
Le Javadoc pour getMethod n'est pas explicite, mais il semble qu'il puisse lancer une exception NoSuchMethodException pour les méthodes qui ne sont pas publiques, et votre méthode est privée.
Vous avez besoin que la liste des paramètres soit absolument correcte pour la méthode que vous voulez pour que l'appel réussisse.
J'ai trouvé que de petites étapes sont importantes lors de la réflexion car le compilateur n'aide pas. Écrivez un petit extrait qui appelle exactement la méthode que vous voulez dans ce cas particulier, puis quand cela fonctionne, généralisez-le dans le framework ici. Je me concentrerais sur les paramètres passés.
Le problème de versioning qui peut causer 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.
Puisque vous utilisez la réflexion, vous n'avez peut-être rien à voir avec le versionnage. Certes, cela n'expliquerait pas un comportement différent entre getMethod
et getDeclaredMethods
, parce que 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 réelle?