2015-04-03 12 views
7

Es gibt zwei similiar Frage auf SO:Tief rekursive Objekte Vergleich (wieder einmal)

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

Deep reflective compare equals

aber es lustig ist, keiner von ihnen gibt völlig richtige Antwort auf die Frage.

Was ich und andere Fragen Autoren wirklich wollen, ist eine Methode in irgendeiner Bibliothek, die nur erzählt zwei Objekte gleich sind gegeben oder nicht:

boolean deepEquals(Object obj1, Object obj2)

das heißt ohne jede Ausnahme zu werfen und so weiter.

apache 's EqualsBuilder ist nicht der Weg, weil es nicht tief vergleichen.

Unitils scheint auch schlechte Entscheidung sein, weil ihre Methode true oder false nicht zurückgibt; Es wird nur eine Ausnahme ausgelöst, wenn der Vergleich fehlgeschlagen ist.

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

scheint, aber es scheint sehr hässlich, und unitils Bibliothek völlig zu schwer für Zwecke vergleichen erforderlich: Natürlich könnte es wie folgt verwendet werden.

Darüber hinaus ist es ziemlich klar, wie man solche deepEquals von selbst erstellen, aber es ist unwahrscheinlich, dass es nicht häufig verwendete Bibliotheken, die bereits implementiert Methode wie folgt enthält. Irgendwelche Ideen?

+0

Rekursiver Vergleich ist nicht trivial. Sehen Sie sich die EqualsBuilder.reflectionEquals-Methode an. Hier können Sie angeben, welche Felder nicht verglichen werden sollen und wie weit Sie in der Klassenhierarchie bei Verwendung der Vererbung zu erreichen sind. Wenn Sie nun ein verschachteltes Objekt haben, das Sie auch mit Reflektion vergleichen möchten, wie können Sie dann erkennen, welche Felder ignoriert werden sollen? Wenn es Ihnen egal ist, dann ist es einfach, die 'EqualsBuilder'-Implementierung einzubinden, um das zu erreichen, was Sie brauchen. Andernfalls müssen Sie möglicherweise Anmerkungen oder eine Registrierung verwenden, um anzugeben, für welche Klasse welche Felder nicht verglichen werden sollen. – krzychu

Antwort

1

Java 1.7 hat Objects.deepEquals(Object a, Object b)

Leider Unitils ‚s ReflectionAssert Klasse keine begleitende Methode, die true oder false zurückgibt. Sie können versuchen:

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

deren DeepEquals Klasse DeepEquals.deepEquals(Object a, Object b) und DeepEquals.deepHashCode(Object o) Methoden, die Sie Ihre Klasse equals und hashCode Methoden verwenden können oder in einem externen Comparator oder Equivalence verwenden außer Kraft zu setzen.

Hinweis: Diese DeepEquals-Implementierung hat eine Einschränkung. Wenn die Klasse über benutzerdefinierte Methoden verfügt, die überschreiben, hat dies Vorrang.

+3

Der Autor der Frage hat es nicht explizit geschrieben, aber ich denke, basierend auf referenzierten Fragen, dass er eine Reflektion gleich, das heißt Objekte vergleichen will, ohne die 'equals' Methode auf ihnen anzuwenden. Der 'Objects.deeepEquals (Objekt a, Objekt b)' vergleicht nicht mit Reflektion. Es basiert auf der Methode "equals" und "deep" bezieht sich auf den Vergleich von Arrays, nicht von Feldern mit Referenztypen. – krzychu

0

Ich glaube nicht, der Apache EqualsBuilder ist eine schreckliche Antwort, aber für eine einfache Schnittstelle, die das tut, was Sie wollen, müssten Sie den Anruf ein wenig wickeln. Hier ist ein Beispiel.

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)); 
} 
Verwandte Themen