9

我们可以使用属性名称找到 setter 方法名称吗?

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

通过使用映射中的键(即propertyName),我需要为对象调用适当的setter 方法并从映射中传递值(即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">

现在我正在迭代地图,当我根据键(名称或公司)处理地图中的每个项目时,我需要调用 A 类的适当 setter 方法,例如,对于第一个项目,我将名称作为键,因此需要调用 new A ().setName。

4

7 回答 7

20

尽管使用反射可以做到这一点,但使用commons-beanutils可能会更好。您可以像这样轻松地使用该setSimpleProperty()方法:

PropertyUtils.setSimpleProperty(a, entry.getKey(), entry.getValue());

假设a是类型A

于 2013-02-27T14:58:56.727 回答
13

如果您使用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 属性编辑器,因此您可以为它不处理的那些注册自定义类型转换器。)

于 2013-02-27T15:18:09.477 回答
5

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

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

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

于 2013-02-27T15:03:07.377 回答
5

使用 Map 放置字段名称及其 Setter 方法名称,或使用字符串连接来“设置”首字母大写的 propertyName 似乎是调用 Setter 方法的一种非常弱的方法。

您知道类名称并且可以遍历其属性并获取每个属性的 Setter/GetterMethod 名称的场景可以像下面的代码片段一样解决。

您可以从 java.beans.* 获取 Introspector / Property Descriptor;

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-07-08T07:03:03.540 回答
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 的性能更高,并且允许您进行 map-bean 转换等等。

免责声明:我是开发 Juffrou-reflect 的人。如果您对如何使用它有任何疑问,我将非常乐意回复。

于 2013-06-15T17:31:16.693 回答
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”来找到 setter 的名称:"set" + capatalizeFieldName(field.getName())

这同样适用于 getter,除了布尔类型使用“is”而不是“get”作为前缀。

于 2016-11-28T10:43:21.250 回答
-1

我认为您可以通过反射来做到这一点,一个更简单的解决方案是对键进行字符串比较并调用适当的方法:

 String key = entry.getKey();
 if ("name".equalsIgnoreCase(key))
   //key
 else
   // company
于 2013-02-27T14:55:33.370 回答