2009-01-23 63 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必须具有类似的功能。