如何使用属性名识别setter方法



我们可以使用属性名找到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包含两个条目:

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

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

虽然这可以通过反射来实现,但最好还是使用common_beauutils。您可以像这样轻松地使用setSimpleProperty()方法:

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

假设aA类型

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

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

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

当然,你会被要求处理一些例外。

使用Map来放置字段名和它的Setter方法名,或者使用字符串连接来使用首字母大写的propertyName来"set"似乎是调用Setter方法的一种非常弱的方法。

如果您知道类名,并且可以遍历它的属性并获得每个属性的Setter/GetterMethod name,则可以像下面的代码片段那样解决。

你可以从java.beans.*;

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

你可以像这样得到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的人。如果你对如何使用它有任何问题,我很乐意回答。

这实际上很重要,因为有关于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;
}

setter的名称可以通过在前面加上"set"来查找:"set" + capatalizeFieldName(field.getName())

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

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

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

相关内容

  • 没有找到相关文章

最新更新