2013-02-27 56 views
2

我們可以使用屬性名稱找到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。

回答

-1

我想你也許可以做到這一點與反思,一個簡單的解決方案正在做的關鍵字符串比較,並調用適當的方法:

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

這不是一個可維護的方法,只能用於快速和簡單的初始化。 – 2013-02-27 15:24:05

13

雖然這是可能使用反射來這樣做,你可能會更好關閉使用commons-beanutils。你可以很容易地使用setSimpleProperty()方法,像這樣:

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

假設aA類型。

+0

不錯的建議! – vikingsteve 2013-02-27 15:00:48

2

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

7

如果您使用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屬性編輯器,所以你可以爲它不處理的那些註冊自定義類型轉換。)

1

你可以得到的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反射的人。如果您對如何使用它有任何疑問,我會很樂意回覆。

3

使用映射來放置字段名稱及其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

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" + capatalizeFieldName(field.getName())

這同樣適用於吸氣劑,不同之處在於布爾類型使用「是」,而不是「獲取「作爲前綴。

相關問題