2009-01-23 71 views
15

我一直在嘗試討論org.apache.commons.beanutils庫的方法/習慣用法,以評估兩個實例之間相等的所有屬性,即Bean的泛型equals()方法。
有沒有一個簡單的方法來做到這一點usnig這個庫?還是我以錯誤的方式去做這件事? 謝謝。如何一般比較整個java bean?

+0

[xtendbeans library](http://stackoverflow.com/a/39222891/421602)可能會在這方面感興趣;請參閱[在其他SO問題上的完整示例](http://stackoverflow.com/a/39222891/421602)。 – vorburger 2016-08-30 08:54:58

回答

16

嘗試EqualsBuilder.reflectionEquals()commons-lang。 EqualsBuilder有一套方法來包含所有字段,所有非瞬態字段以及除某些字段外的所有字段。

如果一切都失敗了,代碼可以作爲一個很好的例子來說明如何實現這一點。

+3

小的增強警告,這不是遞歸的 - 所以如果你有嵌套的bean(即一個bean的屬性是另一個bean),他們需要實現自己的平等。 `reflectionEquals`只是在每個屬性上調用`equals`,它不會進一步反映到類中。 – artbristol 2012-10-08 10:01:30

+1

@artbristol:+1但要小心遞歸等於:當bean形成循環時,可以很容易地陷入循環。 – 2012-10-08 11:52:19

7

要直接回答您的問題,您可以使用反射來進行bean的平等檢查。有幾點需要注意的問題。

有關於equals()和hashcode()的行爲的規則。這些規則談對稱性,consitency和reflexiveness這可能是很難當你的equals方法的行爲動態基於你傳遞在其他物體上做

有趣的閱讀。 http://www.geocities.com/technofundo/tech/java/equalhash.html

一般來說,我覺得你最好創建自己的哈希碼和等於方法。有一個很好的插件可以根據類的屬性自動生成代碼。

說了這麼多,這裏有一些(舊風格)方法得到的getter,setter方法和屬性我很久以前寫道:

private Map getPrivateFields(Class clazz, Map getters, Map setters) { 
    Field[] fields = clazz.getDeclaredFields(); 
    Map m = new HashMap(); 
    for (int i = 0; i < fields.length; i++) { 
     int modifiers = fields[i].getModifiers(); 
     if (Modifier.isPrivate(modifiers) && !Modifier.isStatic(modifiers) && !Modifier.isFinal(modifiers)) { 
      String propName = fields[i].getName(); 
      if (getters.get(propName) != null && setters.get(propName) != null) { 
       m.put(fields[i].getName(), fields[i]); 
      } 
     } 
    } 
    return m; 
} 

使消氣:

private Map getGetters(Class clazz) { 
    Method[] methods = clazz.getMethods(); 
    Map m = new HashMap(); 
    for (int i = 0; i < methods.length; i++) { 
     if (methods[i].getName().startsWith("get")) { 
      int modifiers = methods[i].getModifiers(); 
      if (validAccessMethod(modifiers)) { 
       m.put(getPropertyName(methods[i].getName()), methods[i]); 
      } 
     } 
    } 
    return m; 
} 

而安裝者:

private Map getSetters(Class clazz, Map getters) { 
    Method[] methods = clazz.getMethods(); 
    Map m = new HashMap(); 
    for (int i = 0; i < methods.length; i++) { 
     if (methods[i].getName().startsWith("set")) { 
      int modifiers = methods[i].getModifiers(); 
      String propName = getPropertyName(methods[i].getName()); 
      Method getter = (Method) getters.get(propName); 

      if (validAccessMethod(modifiers) && getter != null) { 
       Class returnType = getter.getReturnType(); 
       Class setType = methods[i].getParameterTypes()[0]; 
       int numTypes = methods[i].getParameterTypes().length; 

       if (returnType.equals(setType) && numTypes == 1) { 
        m.put(propName, methods[i]); 
       } 
      } 
     } 
    } 
    return m; 
} 

也許你可以使用它來推出自己的。

編輯:當然reflectionbuilderAaron Digulla's answer比我的手工好得多。

+0

布爾getter被稱爲isFoo(),所以代碼將需要在getGetters() – 2012-06-15 14:13:21

2

如上所述,基於反射的實現將做你想做的事情。我只是想警告你,這種反映非常昂貴,而且這種實施可能會相當緩慢。如果你只是偶爾進行比較,你會沒事的。但是,如果您有大量的數據集和頻繁的平等檢查(例如過濾大表),您可能會遇到麻煩。

0

或者,雖然沒有直接回答你的問題,但它可能是一個回答您的問題(即除去做樣板代碼是超快的努力)

如果你使用Eclipse,在下面的步驟將自動生成的hashCode和equals你:

源>生成的hashCode和equals ...

,然後選擇字段,它非常有效!:D

乾杯,我希望它能幫助來到這裏的人減少寫一些樣板文件的時間。 PS:我相信其他流行的IDE必須具有類似的功能。