我们可以使用属性名找到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());
假设a
为A
类型
如果您使用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