0

これは、主にJUnitのオブジェクトファクトリのために、オブジェクトのフィールドに怠惰に入力するために私がいじくり回してきたコードですが、これは非常に便利な方法である可能性があります。

    private void lazyObjectFill(Object profil) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
    final Method[] list = profil.getClass().getDeclaredMethods();
    for (Method m : list) {
        if (Modifier.isPublic(m.getModifiers()) && m.getName().startsWith("set")) {

            final Class< ?>[] parameterTypes = m.getParameterTypes();
            if (parameterTypes.length == 1) {
                final Class< ?> clazz = parameterTypes[0];
                if (clazz == String.class) {
                    log.info("Invoking " + m.getName() + " with [\"\"]");
                    m.invoke("");
                } else if (clazz.isPrimitive() && Defaults.defaultValue(clazz) != null) {
                    log.info("Invoking " + m.getName() + " with [" + Defaults.defaultValue(clazz) + "]");
                    m.invoke(Defaults.defaultValue(clazz));
                }
            }

        }
    }
}

このコードをオブジェクトで実行すると、次の例外が発生します。

java.lang.IllegalArgumentException: object is not an instance of declaring class
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:592)

m.invoke( "");を実行すると例外が発生します。文字列セッター。


googlersの利益のためにソースコードを更新しました。

private void lazyObjectFill(Object obj) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
    final Method[] list = obj.getClass().getDeclaredMethods();
    for (Method method : list) {
        method.setAccessible(true);
        if (Modifier.isPublic(method.getModifiers()) && method.getName().startsWith("set")) {

            final Class< ?>[] parameterTypes = method.getParameterTypes();
            if (parameterTypes.length == 1) {
                final Class< ?> clazz = parameterTypes[0];
                if (clazz == String.class) {
                    log.info("Invoking " + method.getName() + " with [\"\"]");
                    method.invoke(obj, "");
                } else if (clazz.isPrimitive() && Defaults.defaultValue(clazz) != null) {
                    log.info("Invoking " + method.getName() + " with [" + Defaults.defaultValue(clazz) + "]");
                    method.invoke(obj, Defaults.defaultValue(clazz));
                }
            }

        }
    }
}
4

3 に答える 3

4

あなたはほとんどそこにいますが、メソッドは静的であり、それらを呼び出すためのオブジェクトが必要です.

すなわち

m.invoke(profil, "");

m.invoke(profil, Defaults.defaultValue(clazz));

パラメータなしで文字列オブジェクトに対してメソッドを実行しようとしていました。文字列クラスにはそのメソッドがないため、失敗する必要がありました。詳細については、メソッドの javadocを参照してください。

ところで:静的メソッドは次のように呼び出されます:

method.invoke(null, params);
于 2010-08-24T13:57:57.730 に答える
2

Method のinvokeメソッドは 2 つの引数を取ることをご存知ですか? その結果、あなたが書いたと思います

m.invoke(profil, "")

その上、私は個人的に String を他のオブジェクトから分離しなかったでしょう。

最後に、オブジェクト フィールドを正しく識別するには、混合アプローチをお勧めします

  1. 非静的フィールド メンバーの列挙を使用する
  2. BeanInfoを使用して Bean プロパティにアクセスします。
于 2010-08-24T13:59:40.660 に答える
1

の最初のパラメーターはMethod.invoke()、メソッドを呼び出すオブジェクトです。

たとえば、あなたの場合m.invoke(profil, "");またはm.invoke(profil, Defaults.defaultValue(clazz));

于 2010-08-24T14:00:09.080 に答える