如何通过属性名识别 setter 方法?

11

我们能否通过属性名找到setter方法的名称?

我有一个动态生成的map<propertyName,propertyValue>

通过使用来自map的键(即propertyName),我需要调用对象的相应setter方法并传递来自map的值(即propertyValue)。

class A {
    String name;
    String age;

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getCompany() {
        return company;
    }
    public void setCompany(String company) {
        this.company = company;
    }
}

我的地图包含两个项目:

map<"name","jack">
map<"company","inteld">

现在我正在迭代这个map,对于map中的每个项目,根据键(名称或公司),我需要调用类A的适当setter方法。例如,对于第一个项目,我得到的键是名称,因此需要调用new A().setName。
7个回答

21
尽管可以使用反射来实现,但最好使用commons-beanutils。您可以轻松地使用setSimpleProperty()方法,如下所示:
PropertyUtils.setSimpleProperty(a, entry.getKey(), entry.getValue());

假设a是类型为A的。

18
如果您使用Spring,那么您很可能希望使用BeanWrapper。(如果不是,您可以考虑使用它。)
Map map = new HashMap();
map.put("name","jack");
map.put("company","inteld");

BeanWrapper wrapper = new BeanWrapperImpl(A.class);
wrapper.setPropertyValues(map);
A instance = wrapper.getWrappedInstance();

这比直接使用反射更容易,因为Spring会为您进行常见的类型转换。(它还会遵守Java属性编辑器,因此您可以为它不处理的自定义类型转换器注册自定义类型转换器。)

5

使用Map来存储字段名和其对应的Setter方法名称,或者使用字符串拼接来“设置”首字母大写的属性名似乎是一种相当薄弱的调用Setter方法的方式。

如果您知道类名并且可以遍历其属性并获取每个属性的Setter/Getter方法名称,则可以像下面的代码片段一样解决这种情况。

您可以从java.beans.*中获取Introspector/PropertyDescriptor。

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

3
在使用纯Java的情况下,我认为这是正确的将字段与其setter匹配的方法。 - JN01

5

反射 API 就是你需要的。假设你知道属性名称,并且有一个类型为 A 的对象 a

 String propertyName = "name";
 String methodName = "set" + StringUtils.capitalize(propertyName);
 a.getClass().getMethod(methodName, newObject.getClass()).invoke(a, newObject);

当然,您将被要求处理一些异常情况。

2
您可以通过以下方式获取setter方法:
A a = new A();
String name = entry.getKey();
Field field = A.class.getField(name);
String methodName = "set" + name.substring(0, 1).toUpperCase() + name.substring(1);
Method setter = bw.getBeanClass().getMethod(methodName, (Class<?>) field.getType());
setter.invoke(a, entry.getValue());

但是它只能用于您的A类。如果您有一个继承基类的类,那么class.getField(name)将不起作用。

您应该查看Juffrou-reflect中的BeanWrapper。它比Springframework更高效,并允许您进行映射 - bean 转换以及更多操作。

声明:我就是开发 Juffrou-reflect 的那个人。如果您对如何使用它有任何问题,我将非常乐意回答。


0

这实际上是有难度的,因为camelCase字段名称的大写规则有特殊规定。根据JavaBeans API(第8.8节),如果字段名称的前两个字符中有任意一个是大写字母,则该字段不会大写。

因此:

  • index 变成 Index -> setIndex()
  • xIndex 仍然是 xIndex -> setxIndex()
  • URL 仍然是 URL -> setURL()

执行此转换的代码如下:

/**
 * Capitalizes the field name unless one of the first two characters are uppercase. This is in accordance with java
 * bean naming conventions in JavaBeans API spec section 8.8.
 *
 * @param fieldName
 * @return the capitalised field name
 * @see Introspector#decapitalize(String)
 */
public static String capatalizeFieldName(String fieldName) {
    final String result;
    if (fieldName != null && !fieldName.isEmpty()
            && Character.isLowerCase(fieldName.charAt(0))
            && (fieldName.length() == 1 || Character.isLowerCase(fieldName.charAt(1)))) {
        result = StringUtils.capitalize(fieldName);
    } else {
        result = fieldName;
    }
    return result;
}

设置器的名称可以通过在字段名称前加上"set"来找到:"set" + capatalizeFieldName(field.getName())

对于获取器,同样适用此方法,只是布尔类型使用"is"作为前缀,而不是"get"。


-1

我认为你可以通过反射来实现,更简单的解决方案是对键进行字符串比较并调用相应的方法:

 String key = entry.getKey();
 if ("name".equalsIgnoreCase(key))
   //key
 else
   // company

这不是可维护的方法,只应用于快速脏初始化。 - Alan Krueger

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接