2015-04-03 11 views
7

ci sono due domanda simile su SO:ricorsiva profonda oggetti di confronto (ancora una volta)

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

Deep reflective compare equals

ma, è divertente, nessuno di loro dà risposta pienamente corretta alla domanda.

quello che io e gli autori di altre domande vuole veramente, è un metodo in qualche libreria che basta dire sono dati due oggetti uguali o no:

boolean deepEquals(Object obj1, Object obj2)

cioè senza lanciare alcuna eccezione e così via.

apache ''s non è il modo, perché non confronta in profondità.

Unitils sembra essere una decisione sbagliata, perché il suo metodo non restituisce true o false; getta solo un'eccezione se il confronto è fallito. Certo, potrebbe essere utilizzato in questo modo:

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

ma sembra molto brutto, e unitils biblioteca sembra del tutto ad essere troppo difficile per confrontare richiesto scopi.

Inoltre, è abbastanza chiaro come creare tale deepEquals da solo, ma è improbabile che non ci siano librerie usate più comuni che contengono un metodo già implementato come questo. Qualche idea?

+0

Il confronto ricorsivo non è banale. Osserva il metodo 'EqualsBuilder.reflectionEquals' - ti consente di specificare quali campi non devono essere confrontati e in che misura raggiungere l'albero gerarchico delle classi quando si utilizza l'ereditarietà. Ora se hai un oggetto nidificato che vuoi anche confrontare usando il reflection, come puoi dire quali campi ignorare? Se non ti interessa, allora è semplice implementare l'implementazione di 'EqualsBuilder' per ottenere ciò che ti serve. Altrimenti potrebbe essere necessario utilizzare annotazioni o un registro per indicare per quale classe quali campi non confrontare. – krzychu

risposta

1

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

Purtroppo Unitils s' ReflectionAssert classe non dispone di un metodo di accompagnamento che restituisce true o false. Si può provare:

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

cui DeepEquals classe ha DeepEquals.deepEquals(Object a, Object b) e DeepEquals.deepHashCode(Object o) metodi che è possibile utilizzare per sovrascrivere equals e hashCode i metodi di tua classe o utilizzare in un esterno Comparator o Equivalence.

Nota: questa implementazione di DeepEquals ha una limitazione. Se la classe ha un metodo definito uguale a override definito dall'utente, avrà la precedenza.

+3

L'autore della domanda non l'ha scritto esplicitamente, ma penso basandomi su domande referenziate, che vuole una riflessione uguale, cioè confrontando gli oggetti, senza implementare il metodo 'equals' su di essi. 'Objects.deepEquals (Object a, Object b)' non si confronta con il reflection. Si basa sul metodo 'equals' e' deep' fa riferimento al confronto di matrici, non a campi con tipi di riferimento. – krzychu

0

Non credo che Apache EqualsBuilder sia una risposta terribile, ma per un'interfaccia semplice che fa ciò che si desidera, è necessario avvolgere un po 'la chiamata. Ecco un esempio.

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)); 
} 
Problemi correlati