web-dev-qa-db-fra.com

Erreur de nombre d'arguments incorrect lors de l'appel d'une méthode

J'ai la classe AClass et une méthode someMethod qui obtient un tableau Object comme paramètre.

public class AClass {
    public void someMethod(Object[] parameters) {
    }
}

En général, lorsque j'essaie d'invoquer cette méthode sur l'objet que j'ai créé et de donner un tableau d'objets en paramètre à cette méthode

Object[] parameters; // lets say this object array is null
Class class = Class.forName("AClass");
Object anObject = class.newInstance();

Method someMethod = class.getDeclaredMethod("someMethod", parameters.getClass());
someMethod.invoke(anObject, parameters);

J'obtiens "erreur de nombre d'arguments incorrect". Qu'est-ce que je rate?

26
iargin

Ce sera bien.

    Object[] parameters ={new Object()}; // lets say this object array is null
    Class clas = Class.forName("AClass");
    Object anObject = clas.newInstance();

    Object[] param ={parameters};

    Method someMethod = clas.getDeclaredMethod("someMethod", parameters.getClass());
    someMethod.invoke(anObject, param);

Faites attention au deuxième paramètre de la méthode invoke. C'est Object [] lui-même, et le type d'argument de votre méthode est Object [] également.

23
biaobiaoqi

Pour développer un peu ce que disent orien et biaobiaoqi. . .

Ce qui vous dérange probablement ici, c'est que Method.invoke(Object, Object...) peut généralement prendre les arguments "en ligne", pour ainsi dire; lorsque le compilateur voit quelque chose comme someMethod.invoke(someObject, arg1, arg2), il crée implicitement un tableau new Object[]{arg1, arg2} puis passe ce tableau à Method.invoke. Method.invoke Passe ensuite les éléments de ce tableau comme arguments à la méthode que vous invoquez. Jusqu'ici tout va bien.

Mais lorsque le compilateur voit quelque chose comme someMethod.invoke(someObject, someArray), il suppose que vous avez déjà empaqueté les arguments dans un tableau; afin de ne plus les reconditionner. Ainsi, Method.invoke Essaiera de passer les éléments de someArray comme arguments à la méthode que vous invoquez, plutôt que de passer someArraylui-même comme argument.

(C'est toujours ainsi que fonctionne la notation ...; Elle accepte soit un tableau contenant des éléments du type approprié, o zéro ou plusieurs arguments du type approprié .)

Ainsi, comme l'ont dit orien et biaobiaoqi, vous devez reconditionner votre parameters dans un tableau supplémentaire, new Object[] {parameters}, Afin que parameters lui-même finisse par être transmis à votre méthode.

Cela a-t-il du sens?

11
ruakh

La méthode Method.invoke prend l'objet pour recevoir l'appel de méthode et un tableau des arguments de la méthode. Comme votre méthode prend un argument, le tableau donné doit avoir une taille d'un.

essayez de créer un nouveau tableau de taille 1:

someMethod.invoke(anObject, new Object[] {parameters});

Notez que la seule valeur de ce tableau peut être nulle. Cela simulerait anObject.someMethod(null)

9
orien

Les paramètres de invoke sont un tableau de Object; vos paramètres doivent être un Object[]contenant le Object[] que vous passez à someMethod.

Vous n'avez pas besoin de créer un tableau immédiat pour le faire, car la signature invoke est invoke(Object, Object...), mais dans votre cas, vous essayez de passer un vide tableau. Si vous souhaitez passer null:

Object[] parameters = { null };
...
someMethod.invoke(anObject, parameters);

En fin de compte, cependant, les autres réponses sont correctes: vous devez passer un Object[] Contenant une entrée pour chacun des paramètres des méthodes.

4
Dave Newton

essaye ça:

    someMethod.invoke(anObject, new .Java.lang.Object[1][]{parameters});

J'ai obtenu en générant automatiquement une version de l'API Reflection de votre code avec dp4j:

$ javac -cp dp4j-1.2-jar-with-dependencies.jar -Averbose=true AClass.Java
AClass.Java:10: Note: 
import com.dp4j.*;

public class AClass {

    public AClass() {
        super();
    }

    public void someMethod(Object[] parameters) {
    }

    @Reflect(all = true)
    public static void main(String... args) throws ... {
        Object[] parameters = null;
        ...
        AClass anObject;
        anObject = (.AClass)aClassConstructor.newInstance();
        Java.lang.reflect.Method someMethodWithArrayMethod = null;
        someMethodWithArrayMethod = Class.forName("AClass").getDeclaredMethod("someMethod", .Java.lang.Object[].class);
        someMethodWithArrayMethod.setAccessible(true);
        someMethodWithArrayMethod.invoke(anObject, new .Java.lang.Object[1][]{parameters});
    }
}
1
simpatico