深度递归对象比较(再次)

2022-09-04 22:53:52

SO上有两个类似的问题:

有没有一个Java实用程序可以对两个对象进行深入比较?

深度反射比较等于

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

我和其他问题的作者真正想要的是某个库中的某种方法,它只会判断给定的两个对象是否相等:

boolean deepEquals(Object obj1, Object obj2)

即不抛出任何异常等。

apache的不是解决方案,因为它没有深入的比较。EqualsBuilder

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

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

但它似乎非常丑陋,并且库似乎完全太重,无法满足所需的比较目的。unitils

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


答案 1

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

不幸的是,的类没有返回 或 的伴随方法。您可以尝试:UnitilsReflectionAsserttruefalse

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

其类具有和方法,可用于重写类和方法或在外部或 中使用。DeepEqualsDeepEquals.deepEquals(Object a, Object b)DeepEquals.deepHashCode(Object o)equalshashCodeComparatorEquivalence

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


答案 2

我不认为Apache是一个糟糕的答案,但是对于一个简单的接口,你可以做你想要的,你需要把调用包装一下。下面是一个示例。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));
}