2015-04-03 49 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)); 
}