我们可以使用属性名称找到setter方法名吗?
我有动态生成的map<propertyName,propertyValue>
通过使用map中的键(这是propertyName),我需要为object调用适当的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">
现在我正在迭代地图,当我从地图继续处理每个项目时,基于键(名称或公司)我需要调用适当的A类setter方法 例如对于第一项,我将名称作为键,因此需要调用新的A()。setName。
答案 0 :(得分:17)
尽管使用反射可以做到这一点,但最好还是使用commons-beanutils。您可以轻松使用setSimpleProperty()
方法,如下所示:
PropertyUtils.setSimpleProperty(a, entry.getKey(), entry.getValue());
假设a
的类型为A
。
答案 1 :(得分:12)
如果您使用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属性编辑器,以便您可以为它不能处理的那些注册自定义类型转换器。)
答案 2 :(得分:5)
使用Map放置字段名称及其Setter方法名称,或使用字符串连接来设置&#34;设置&#34;使用First Letter大写的propertyName似乎是一种调用Setter方法的相当弱的方法。
您知道类名称并且可以迭代其属性并获取每个Property的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();}
答案 3 :(得分:4)
Reflection API
就是您所需要的。假设您知道属性名称,并且您有a
类型的对象A
:
String propertyName = "name";
String methodName = "set" + StringUtils.capitalize(propertyName);
a.getClass().getMethod(methodName, newObject.getClass()).invoke(a, newObject);
当然,你会被要求处理一些例外情况。
答案 4 :(得分: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的人。如果您对如何使用它有任何疑问,我将非常乐意回复。
答案 5 :(得分:0)
这实际上是非常重要的,因为有关于camelCase字段名称大写的特殊规则。根据JavaBeans API(第8.8节),如果字段名称的前两个字符中的任何一个是大写字母,则该字段不是大写的。
因此
index
变为Index
- &gt; setIndex()
xIndex
保持为xIndex
- &gt; setxIndex()
URL
保持为URL
- &gt; 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;
}
然后可以通过预先设置&#34; set&#34;找到setter的名称。在它前面:"set" + capatalizeFieldName(field.getName())
这同样适用于getter,除了布尔类型使用&#34;是&#34;而不是&#34;得到&#34;作为前缀。
答案 6 :(得分:-1)
我认为你可以用反射来做到这一点,一个更简单的解决方案是在键上进行字符串比较并调用适当的方法:
String key = entry.getKey();
if ("name".equalsIgnoreCase(key))
//key
else
// company