web-dev-qa-db-ja.com

メソッドの呼び出し時に誤った数の引数エラー

クラスAClassと、パラメータとしてsomeMethod配列を取得するメソッドObjectがあります。

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

主に、私が作成したオブジェクトでこのメソッドを呼び出して、このメソッドのパラメーターとしてオブジェクト配列を指定しようとすると

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);

「引数の数エラー」エラーが発生します。何が欠けていますか?

26
iargin

それで大丈夫です。

    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);

Invokeメソッドの2番目のパラメーターに注意してください。これはObject []自体であり、メソッドの引数の型もObject []です。

23
biaobiaoqi

Orienとbiaobiaoqiが言っていることを少し拡大する。 。 。

ここでおそらくあなたを混乱させているのは、Method.invoke(Object, Object...)は通常、いわば「インライン」で引数を取ることができるということです。コンパイラがsomeMethod.invoke(someObject, arg1, arg2)のようなものを見つけると、暗黙的に配列_new Object[]{arg1, arg2}_を作成し、その配列を_Method.invoke_に渡します。 _Method.invoke_は、その配列の要素を引数として、呼び出しているメソッドに渡します。ここまでは順調ですね。

しかし、コンパイラがsomeMethod.invoke(someObject, someArray)のようなものを検出すると、引数がすでに配列にパッケージ化されていると想定します。したがって、再度パッケージ化されることはありません。したがって、_Method.invoke_は、someArrayitselfを引数として渡すのではなく、呼び出すメソッドにsomeArrayelementsを引数として渡そうとします。

(これは常に_..._表記がどのように機能するかです。これはor適切なタイプの要素を含む配列、or適切なタイプの0個以上の引数を受け入れます。 )

したがって、orienとbiaobiaoqiが言ったように、parametersを追加の配列_new Object[] {parameters}_に再ラップして、parameters自体がメソッドに渡されるようにする必要があります。

それは理にかなっていますか?

11
ruakh

Method.invokeメソッドは、オブジェクトを受け取り、メソッド呼び出しと、メソッドへの引数の配列を受け取ります。メソッドは1つの引数を取るため、指定された配列のサイズは1でなければなりません。

サイズ1の新しい配列を作成してみてください:

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

この配列の1つの値がnullになる可能性があることに注意してください。これはanObject.someMethod(null)をシミュレートします

9
orien

invokeのパラメーターはObjectの配列です。パラメータは_Object[]_ containing _Object[]_に渡すsomeMethodにする必要があります。

invokeシグネチャはinvoke(Object, Object...)であるため、これを行うために直接配列を作成する必要はありませんが、あなたの場合はで渡そうとしています空配列。 nullを渡したい場合:

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

ただし、結局のところ、他の答えは正しいです。各メソッドパラメータのエントリを含む_Object[]_を渡す必要があります。

4
Dave Newton

これを試して:

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

私は、dp4jを使用してコードのReflection APIバージョンを自動的に生成しました。

$ 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