51

リフレクションを使用してクラスのセッター メソッドを呼び出す必要があり、コードは次のとおりです。

try {             
   Method method = myObj.getClass().getMethod("set" + fieldName, new Class[] { value.getClass() });               
   method.invoke(myObj, value);
     } catch (Exception ex) {
         ex.printStackTrace();
     }

valueanArrayListであり、setter メソッドは次のとおりです。

public void setNames(List<String> names){
    this.names = names;
}

このコードを実行するとAjava.lang.NoSuchMethodExceptionがスローされますが、セッター メソッドのパラメーターの型がArrayListからに変更されると、List正常に実行されます。クラスからメソッドを取得するときにパラメーターの型を手動で指定せずに、setter メソッドのパラメーターをスーパー型に保持し、引き続きリフレクションを使用する方法はありますか?

4

7 に答える 7

57

BeanUtilsを使用できます:

ステップ1

Customer customer = new Customer();

ステップ2

BeanUtils.setProperty(customer,"firstName","Paul Young");

顧客オブジェクトが次のようになっていると仮定して、リフレクションを使用してすべてのクラスメンバーを反復処理し、それに応じて値を設定できます。

private String firstName;
// Getter and Setter are defined
于 2012-07-05T07:48:46.813 に答える
55

Spring Frameworkを使用する場合は、 PropertyAccessorFactoryを使用してPropertyAccessorインターフェースの実装を取得できます。

プロパティへの直接アクセス

PropertyAccessor myAccessor = PropertyAccessorFactory.forDirectFieldAccess(object);
// set the property directly, bypassing the mutator (if any)
myAccessor.setPropertyValue("someProperty", "some value");

アクセサー/ミューテーターによるプロパティへのアクセス

gettersetterを使用してプロパティにアクセスする必要がある場合は、代わりに次のforBeanPropertyAccessメソッド を使用できます。

PropertyAccessor myAccessor = PropertyAccessorFactory.forBeanPropertyAccess(object);
// a `setSomeProperty()` method will be used
myAccessor.setPropertyValue("someProperty", "some value");
于 2013-04-12T13:46:10.260 に答える
26

他の答えとは対照的に、本当に簡単な解決策があります。を参照してくださいjava.beans.Statement。実際の型と正式な型 (およびその他のいくつか) を気にすることなく、任意のリフレクション コードを実行する方法を提供します。

于 2012-04-04T10:25:13.797 に答える
4

簡単な解決策がありますが、その単純さにはパフォーマンスが犠牲になります。

代わりにこのモンスターを使用しています。

public static Method findMethod(Class<?> clazz, String methodName, Class<?>... parameterTypes) throws NoSuchMethodException {

    // First try the trivial approach. This works usually, but not always.
    try {
        return clazz.getMethod(methodName, parameterTypes);
    } catch (NoSuchMethodException ex) {
    }

    // Then loop through all available methods, checking them one by one.
    for (Method method : clazz.getMethods()) {

        String name = method.getName();
        if (!methodName.equals(name)) { // The method must have right name.
            continue;
        }

        Class<?>[] acceptedParameterTypes = method.getParameterTypes();
        if (acceptedParameterTypes.length != parameterTypes.length) { // Must have right number of parameters.
            continue;
        }

        boolean match = true;
        for (int i = 0; i < acceptedParameterTypes.length; i++) { // All parameters must be right type.
            if (null != parameterTypes[i] && !acceptedParameterTypes[i].isAssignableFrom(parameterTypes[i])) {
                match = false;
                break;
            }
            if (null == parameterTypes[i] && acceptedParameterTypes[i].isPrimitive()) { // Accept null except for primitive fields.
                match = false;
                break;
            }
        }

        if (match) {
            return method;
        }

    }

    // None of our trials was successful!
    throw new NoSuchMethodException();
}

parameterTypesから得られるものですvalue.getClass()。それらの一部またはすべてが null になることもあります。次に、非プリミティブ パラメータ フィールドのマットとして扱われます。

これでも完全ではありません。ポリモーフィックに適したメソッドがいくつかあるが、どれも完全に一致しない場合、返されるメソッドは任意に選択されclazz.getMethods()ます (返される配列で最初に一致したものが取得されます)。この動作は、「最も近い一致」が常に使用される Java 言語の動作とは異なります。

メソッドを名前で取得するだけで十分な場合 (つまり、名前が一致する場合にパラメーターが適切であると想定する場合)、はるかに簡単に (そしていくらか高速に) 管理できます。

public static Method findMethod(Class<?> clazz, String methodName) {
  for (Method method : clazz.getMethods()) {
    if (method.getName().equals(methodName)) {
      return method;
    }
  }
  throw new NoSuchMethodException();
} 

さらにブーストするには、ある種のキャッシュを検討してください。

于 2012-04-04T10:18:26.863 に答える
3

リフレクション クラスは、動的呼び出しと呼ばれることもあります。

たとえば、リフレクションを使用して getter メソッドを見てみましょう

というクラスがありMyReflectionClass、 というメソッドがあるとしgetreflect()ます。(例: type string) リフレクション クラスの使用方法を見てみましょう

MyReflectionClass  obj = new MyReflectionClass();

<? extends MyReflectionClass> tempClass = obj.getClass();
String a = (String) obj.getMethod("getreflect").invoke(obj);

now セッターメソッド

(String) obj.getDeclaredMethod("setreflect", String.class).invoke(obj,"MyString");

文字列のシーケンスで同じ操作を行う必要がある場合

    (String) obj.getDeclaredMethod("setreflect",
 new String.class{}).invoke(obj,"MyString1","MyString2");

それが役に立つことを願っています

于 2014-09-25T16:14:44.707 に答える
1

例 set ResultSet で値を取得する setters メソッドを使用するすべてのフィールド。

private Object setAllSetters(Object ob, ResultSet rs) throws SQLException{
    // MZ: Find the correct method
    Class cls = ob.getClass();
    while (rs.next()) {
        for (Field field : cls.getDeclaredFields()){
            for (Method method : cls.getMethods())
            {
                if ((method.getName().startsWith("set")) && (method.getName().length() == (field.getName().length() + 3)))
                {
                    if (method.getName().toLowerCase().endsWith(field.getName().toLowerCase()))
                    {
                        // MZ: Method found, run it
                        try
                        {
                            method.setAccessible(true);
                            if(field.getType().getSimpleName().toLowerCase().endsWith("integer"))
                                method.invoke(ob,rs.getInt(field.getName().toLowerCase()));
                            else if(field.getType().getSimpleName().toLowerCase().endsWith("long"))
                                method.invoke(ob,rs.getLong(field.getName().toLowerCase()));
                            else if(field.getType().getSimpleName().toLowerCase().endsWith("string"))
                                method.invoke(ob,rs.getString(field.getName().toLowerCase()));
                            else if(field.getType().getSimpleName().toLowerCase().endsWith("boolean"))
                                method.invoke(ob,rs.getBoolean(field.getName().toLowerCase()));
                            else if(field.getType().getSimpleName().toLowerCase().endsWith("timestamp"))
                                method.invoke(ob,rs.getTimestamp(field.getName().toLowerCase()));
                            else if(field.getType().getSimpleName().toLowerCase().endsWith("date"))
                                method.invoke(ob,rs.getDate(field.getName().toLowerCase()));
                            else if(field.getType().getSimpleName().toLowerCase().endsWith("double"))
                                method.invoke(ob,rs.getDouble(field.getName().toLowerCase()));
                            else if(field.getType().getSimpleName().toLowerCase().endsWith("float"))
                                method.invoke(ob,rs.getFloat(field.getName().toLowerCase()));
                            else if(field.getType().getSimpleName().toLowerCase().endsWith("time"))
                                method.invoke(ob,rs.getTime(field.getName().toLowerCase()));
                            else 
                                method.invoke(ob,rs.getObject(field.getName().toLowerCase()));
                        }
                        catch (IllegalAccessException | InvocationTargetException | SQLException e)
                        {
                            System.err.println(e.getMessage());
                        }
                    }
                }
            }
        }
    }
    return ob;
}
于 2013-08-06T17:34:14.903 に答える
0

文字列処理を使用してメソッド名を検出することは、正しい方法とは思えないかもしれません。解決策の一つと考えてください。

    try {
            Animal animal = new Animal();
            BeanInfo beaninfo = Introspector.getBeanInfo(Animal.class);
            PropertyDescriptor pds[] = beaninfo.getPropertyDescriptors();
            Method setterMethod=null;
            for(PropertyDescriptor pd : pds) { 
                setterMethod = pd.getWriteMethod(); // For Setter Method

           /*
               You can get Various property of Classes you want. 
           */

                System.out.println(pd.getName().toString()+ "--> "+pd.getPropertyType().toString()+"--Setter Method:->"+pd.getWriteMethod().toString());

                if(setterMethod == null) continue;
                else
                    setterMethod.invoke(animal, "<value>");
            }
        }catch(Exception e) {e.printStackTrace();}
于 2016-06-16T06:45:55.977 に答える