使用java反射调用setter方法

Dil*_*sha 34 java reflection

我需要使用反射调用类的setter方法,代码如下:

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

value是一个ArrayList以及设置器方法如下:

public void setNames(List<String> names){
    this.names = names;
}
Run Code Online (Sandbox Code Playgroud)

java.lang.NoSuchMethodException运行此代码时抛出A ,但当setter方法参数类型更改为ArrayListfrom时List,执行正常.有没有办法将setter方法参数保持在超类型中并且仍然使用反射而无需在从类中获取方法时手动给出参数的类型?

Ana*_*and 49

你可以使用BeanUtils:

步骤1

Customer customer = new Customer();
Run Code Online (Sandbox Code Playgroud)

第2步

BeanUtils.setProperty(customer,"firstName","Paul Young");
Run Code Online (Sandbox Code Playgroud)

您可以使用反射迭代所有类成员并相应地设置值,假设客户对象具有:

private String firstName;
// Getter and Setter are defined
Run Code Online (Sandbox Code Playgroud)


el.*_*omo 46

如果您碰巧使用spring框架,则可以使用PropertyAccessorFactory来检索PropertyAccessor接口的实现:

直接访问属性

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

通过访问器/更改器访问属性

如果您需要使用其gettersetter访问您的属性,则可以使用以下forBeanPropertyAccess方法:

PropertyAccessor myAccessor = PropertyAccessorFactory.forBeanPropertyAccess(object);
// a `setSomeProperty()` method will be used
myAccessor.setPropertyValue("someProperty", "some value");
Run Code Online (Sandbox Code Playgroud)

  • 当你使用 Spring 时非常棒。这对我很有帮助。 (2认同)

use*_*421 23

与其他答案相反,有一个非常简单的解决方案.见java.beans.Statement.它为您提供了一种执行任意反射代码的方法,而无需担心实际与正式类型(以及其他一些事情).

  • 查看`java.beans.Statement`的来源,它的缓慢性可以解释为它处理所有这些细节,例如访问修饰符,最具体的多态匹配等.这是一种权衡 - 您是否希望以性能为代价实现简单性,或者以做出一些假设为代价的表现(如果不正确,可能是危险的). (2认同)

Joo*_*kka 5

有一个简单的解决方案,但这种简单性是以性能为代价的。

我正在使用这个怪物:

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();
}
Run Code Online (Sandbox Code Playgroud)

parameterTypes是你从你得到的value.getClass()。其中部分或全部也可以为空。然后它们被视为任何非原始参数字段的匹配。

即使这也不是完美的:如果有多个多态性合适的方法,但没有一个完全匹配,则返回的方法是任意选择的(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();
} 
Run Code Online (Sandbox Code Playgroud)

为了进一步提高它,可以考虑某种缓存。