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

问题描述:

我们可以使用属性名称找到setter方法名称吗?如何识别使用属性名称的setter方法?

我已动态生成map<propertyName,propertyValue>

通过使用从地图键(这是propertyName的)我需要调用为对象相应的方法,并从地图传递值(这是的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类的设定器方法 对于第一项我得到的名称作为关键,所以需要调用新的A()。setName。

我想你也许可以做到这一点与反思,一个简单的解决方案正在做的关键字符串比较,并调用适当的方法:

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

这不是一个可维护的方法,只能用于快速和简单的初始化。 – 2013-02-27 15:24:05

虽然这是可能使用反射来这样做,你可能会更好关闭使用commons-beanutils。你可以很容易地使用setSimpleProperty()方法,像这样:

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

假设aA类型。

+0

不错的建议! – vikingsteve 2013-02-27 15:00:48

Reflection API是你需要的。让我们假设你知道属性的名字,你有A类型的对象a

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

Ofcourse,你会被要求来处理一些例外。

+2

例外,是的,但也缓存了反射查找的结果。还要注意,这个建议要求setter采用一个已知的参数类型('String'),如果你只使用已知的参数类型,这很好,但如果你使用其他对象可能会出错(尤其是涉及继承的地方) )。这就是为什么像beanutils或Spring的BeanWrapper这样的东西值得一看。 – ig0774 2013-02-27 15:19:21

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

你可以得到的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反射的人。如果您对如何使用它有任何疑问,我会很乐意回复。

使用映射来放置字段名称及其Setter方法名称,或使用字符串串联来“设置”第一个字母大写的propertyName似乎是一个很弱的方法来调用Setter方法。

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

您可以从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

海事组织这是正确的方式来匹配一个字段与其setter,使用香草Java。 – JN01 2016-10-26 13:57:38

这实际上是非常平凡的,因为有关于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" + capatalizeFieldName(field.getName())

这同样适用于吸气剂,不同之处在于布尔类型使用“是”,而不是“获取“作为前缀。