2015-04-03 48 views
7

有两个similiar问题上的SO:深递归对象比较(再次)

Is there a Java reflection utility to do a deep comparison of two objects?

Deep reflective compare equals

,但它是有趣的,他们没有给出完全正确的答案的问题。

我和其他问题的作者真正想要的,是在一些图书馆,这将只是告诉给出了两个对象相同或不是一些方法:

boolean deepEquals(Object obj1, Object obj2)

即没有抛出任何异常等。

apacheEqualsBuilder不是这样,因为它没有深入的比较。

Unitils似乎也是不好的决定,因为它的方法不返回truefalse;如果比较失败,它只会引发异常。当然,它也可以使用这样的:

Difference difference = ReflectionComparatorFactory.createRefectionComparator(new ReflectionComparatorMode[]{ReflectionComparatorMode.LENIENT_ORDER, ReflectionComparatorMode.IGNORE_DEFAULTS}).getDifference(oldObject, newObject);

,但它似乎很丑陋,unitils库完全好像是太难为需要比较的目的。

此外,如何自行创建这样的deepEquals是非常清楚的,但是不太可能没有包含已经实现的方法的常用库。有任何想法吗?

+0

递归比较不是微不足道的。看一下'EqualsBuilder.reflectionEquals'方法 - 让我们指定在使用继承时哪些字段不能进行比较以及在类层次结构树中到达多远。现在如果你有一个嵌套的对象,你也想用反射来比较,你怎么知道要忽略哪些字段?如果你不在乎,那么包装'EqualsBuilder'实现很简单,以实现你所需要的。否则,您可能需要使用注释或注册表来告诉哪些类不能比较哪些字段。 – krzychu 2017-03-20 06:47:22

回答

1

的Java 1.7具有Objects.deepEquals(Object a, Object b)

不幸的是UnitilsReflectionAssert类没有伴随方法返回truefalse。你可以试试:

https://github.com/jdereg/java-util

DeepEquals类有DeepEquals.deepEquals(Object a, Object b)DeepEquals.deepHashCode(Object o)方法,你可以用它来覆盖你的类的equalshashCode方法或使用外部ComparatorEquivalence

注意:此DeepEquals实施有一个限制。如果该类具有用户定义的重写equals方法,则该优先。

+3

该问题的作者没有明确写出,但我认为基于引用的问题,他希望反射等于,即比较对象,而不对其执行“equals”方法。 'Objects.deepEquals(Object a,Object b)'不使用反射进行比较。它依赖于'equals'方法,'deep'部分是指比较数组,而不是引用类型的字段。 – krzychu 2017-03-20 06:39:57

0

我不认为阿姆斯特丹EqualsBuilder是一个可怕的答案,但对于一个简单的接口,做你想做的事情,你需要包装一下这个调用。这是一个例子。

public static <T> boolean matches(T actual, T expected, String... excludedFields) { 
    assert actual != null; 
    assert expected != null; 
    boolean matches = EqualsBuilder.reflectionEquals(actual, expected, 
      false /* testTransients */, 
      null /* reflectUpToClass */, 
      true /* testRecursive */, 
      excludedFields); 
    if (!matches) { 
     log.warn("Actual result doesn't match."); 
     logComparison(actual, expected); 
    } 
    return matches; 
} 

public static <T> void logComparison(T actual, T expected) { 
    //Making sure hashcodes don't thrown an exception 
    assert actual.hashCode() > Integer.MIN_VALUE; 
    assert expected.hashCode() > Integer.MIN_VALUE; 
    log.warn("Expected: \n" + reflectionToString(expected)); 
    log.warn("Actual: \n" + reflectionToString(actual)); 
}