Wie kann ich Gleichheit für zwei Klassen ohne eine Gleichheitsmethode behaupten?

111

Angenommen, ich habe eine Klasse ohne equals () -Methode, für die die Quelle nicht vorhanden ist. Ich möchte die Gleichheit in zwei Fällen dieser Klasse behaupten.

Ich kann mehrere Behauptungen aufstellen:

assertEquals(obj1.getFieldA(), obj2.getFieldA());
assertEquals(obj1.getFieldB(), obj2.getFieldB());
assertEquals(obj1.getFieldC(), obj2.getFieldC());
...

Ich mag diese Lösung nicht, weil ich nicht das vollständige Gleichheitsbild bekomme, wenn eine frühe Behauptung fehlschlägt.

Ich kann manuell manuell vergleichen und das Ergebnis verfolgen:

String errorStr = "";
if(!obj1.getFieldA().equals(obj2.getFieldA())) {
    errorStr += "expected: " + obj1.getFieldA() + ", actual: " + obj2.getFieldA() + "\n";
}
if(!obj1.getFieldB().equals(obj2.getFieldB())) {
    errorStr += "expected: " + obj1.getFieldB() + ", actual: " + obj2.getFieldB() + "\n";
}
...
assertEquals("", errorStr);

Dies gibt mir das vollständige Gleichheitsbild, ist aber klobig (und ich habe mögliche Nullprobleme nicht einmal berücksichtigt). Eine dritte Option ist die Verwendung von Comparator, aber compareTo () sagt mir nicht, welche Felder nicht gleich sind.

Gibt es eine bessere Methode, um das, was ich will, aus dem Objekt herauszuholen, ohne dass Unterklassen und Überschreibungen gleich sind (ugh)?

Ryan Nelson
quelle
Suchen Sie eine Bibliothek, die einen tiefen Vergleich für Sie bietet? wie Deep-Equals unter stackoverflow.com/questions/1449001/… vorgeschlagen ?
Vikdor
3
Warum müssen Sie wissen, warum die beiden Instanzen nicht gleich waren? Normalerweise equalsagt eine Implementierung der Methode nur aus, ob zwei Instanzen gleich sind, und es ist uns egal, warum die Intanzen nicht gleich sind.
Bhesh Gurung
3
Ich möchte wissen, welche Eigenschaften ungleich sind, damit ich sie beheben kann. :)
Ryan Nelson
Alle Objecthaben eine equalsMethode, Sie meinten wahrscheinlich keine überschriebene Gleichheitsmethode.
Steve Kuo
Der beste Weg, den ich mir
vorstellen

Antworten:

66

Mockito bietet einen Reflection-Matcher:

Für die neueste Version von Mockito verwenden Sie:

Assert.assertTrue(new ReflectionEquals(expected, excludeFields).matches(actual));

Für ältere Versionen verwenden Sie:

Assert.assertThat(actual, new ReflectionEquals(expected, excludeFields));
felvhage
quelle
17
Diese Klasse ist im Paket org.mockito.internal.matchers.apachecommons. Mockito-Dokumente geben Folgendes an: org.mockito.internal-> "Interne Klassen, die nicht von Clients verwendet werden dürfen." Damit setzen Sie Ihr Projekt einem Risiko aus. Dies kann sich in jeder Mockito-Version ändern. Lesen Sie hier: site.mockito.org/mockito/docs/current/overview-summary.html
luboskrnac
6
Verwenden Sie Mockito.refEq()stattdessen.
Jeremy Kao
1
Mockito.refEq()schlägt fehl, wenn die Objekte keine ID gesetzt haben = (
cavpollo
1
@PiotrAleksanderChmielowski, sorry, wenn Sie mit Spring + JPA + Entities arbeiten, hat das Entity-Objekt möglicherweise eine ID (die das ID-Feld der Datenbanktabelle darstellt). Wenn es also leer ist (ein neues Objekt, das noch nicht in der Datenbank gespeichert ist), refEqschlägt dies fehl zu vergleichen, da die Hashcode-Methode die Objekte nicht vergleichen kann.
Cavpollo
3
Es funktioniert gut, aber erwartet und tatsächlich sind in falscher Reihenfolge. Es sollte umgekehrt sein.
pkawiak
48

Hier gibt es viele richtige Antworten, aber ich möchte auch meine Version hinzufügen. Dies basiert auf Assertj.

import static org.assertj.core.api.Assertions.assertThat;

public class TestClass {

    public void test() {
        // do the actual test
        assertThat(actualObject)
            .isEqualToComparingFieldByFieldRecursively(expectedObject);
    }
}

UPDATE: In assertj v3.13.2 ist diese Methode veraltet, wie Woodz im Kommentar ausgeführt hat. Aktuelle Empfehlung ist

public class TestClass {

    public void test() {
        // do the actual test
        assertThat(actualObject)
            .usingRecursiveComparison()
            .isEqualTo(expectedObject);
    }

}
Thomas
quelle
3
In assertj v3.13.2 wird diese Methode veraltet und die Empfehlung ist jetzt auf den Einsatz usingRecursiveComparison()mit isEqualTo(), so dass die LinieassertThat(actualObject).usingRecursiveComparison().isEqualTo(expectedObject);
Woodz
45

Ich implementiere diesen Anwendungsfall im Allgemeinen mit org.apache.commons.lang3.builder.EqualsBuilder

Assert.assertTrue(EqualsBuilder.reflectionEquals(expected,actual));
Abhijeet Kushe
quelle
1
Gradle: androidTestCompile 'org.apache.commons: commons-lang3: 3.5'
Roel
1
Sie müssen dies zu Ihrer Gradle-Datei unter "Abhängigkeiten" hinzufügen, wenn Sie "org.apache.commons.lang3.builder.EqualsBuilder"
Roel
3
Dies gibt keinen Hinweis darauf, welche genauen Felder tatsächlich nicht übereinstimmten.
Vadzim
1
@Vadzim Ich habe den folgenden Code verwendet, um Assert.assertEquals (ReflectionToStringBuilder.toString (erwartet), ReflectionToStringBuilder.toString (tatsächlich)) abzurufen.
Abhijeet Kushe
2
Dies erfordert, dass alle Knoten im Diagramm "gleich" und "Hashcode" implementieren, was diese Methode im Grunde genommen nahezu unbrauchbar macht. AssertJs isEqualToComparingFieldByFieldRecursively funktioniert in meinem Fall perfekt.
John Zhang
12

Ich weiß, dass es ein bisschen alt ist, aber ich hoffe, es hilft.

Ich habe das gleiche Problem wie Sie, daher habe ich nach einer Untersuchung nur wenige ähnliche Fragen gefunden wie diese, und nachdem ich die Lösung gefunden habe, beantworte ich dasselbe in diesen, da ich dachte, es könnte anderen helfen.

Die am häufigsten gewählte Antwort (nicht die vom Autor ausgewählte) auf diese ähnliche Frage ist die für Sie am besten geeignete Lösung.

Grundsätzlich besteht es aus der Verwendung der Bibliothek Unitils .

Dies ist die Verwendung:

User user1 = new User(1, "John", "Doe");
User user2 = new User(1, "John", "Doe");
assertReflectionEquals(user1, user2);

Was auch dann passieren wird, wenn die Klasse Usernicht implementiert equals(). Weitere Beispiele und eine wirklich coole Behauptung finden Sie assertLenientEqualsin ihrem Tutorial .

lopezvit
quelle
1
Scheint leider Unitilsgestorben zu sein, siehe stackoverflow.com/questions/34658067/is-unitils-project-alive .
Ken Williams
8

Sie können Apache commons lang ReflectionToStringBuilder verwenden

Sie können entweder die Attribute, die Sie testen möchten, einzeln angeben oder besser diejenigen ausschließen, die Sie nicht möchten:

String s = new ReflectionToStringBuilder(o, ToStringStyle.SHORT_PREFIX_STYLE)
                .setExcludeFieldNames(new String[] { "foo", "bar" }).toString()

Anschließend vergleichen Sie die beiden Zeichenfolgen wie gewohnt. Für den Punkt, dass die Reflexion langsam ist, gehe ich davon aus, dass dies nur zum Testen dient und daher nicht so wichtig sein sollte.

Matthew Farwell
quelle
1
Ein zusätzlicher Vorteil dieses Ansatzes besteht darin, dass Sie eine visuelle Ausgabe erhalten, in der erwartete und tatsächliche Werte als Zeichenfolgen ohne Felder angezeigt werden, die Sie nicht interessieren.
fquinner
7

Wenn Sie hamcrest für Ihre Asserts (assertThat) verwenden und keine zusätzlichen Testbibliotheken abrufen möchten, können Sie SamePropertyValuesAs.samePropertyValuesAsElemente aktivieren, für die keine überschriebene Gleichheitsmethode vorhanden ist.

Der Vorteil ist, dass Sie kein weiteres Testframework aufrufen müssen und es einen nützlichen Fehler gibt, wenn die Zusicherung fehlschlägt ( expected: field=<value> but was field=<something else>), anstatt expected: true but was falsewenn Sie so etwas verwenden EqualsBuilder.reflectionEquals().

Der Nachteil ist, dass es sich um einen flachen Vergleich handelt und es keine Option zum Ausschließen von Feldern gibt (wie in EqualsBuilder), sodass Sie verschachtelte Objekte umgehen müssen (z. B. entfernen und unabhängig voneinander vergleichen).

I'm besten fall:

import static org.hamcrest.beans.SamePropertyValuesAs.samePropertyValuesAs;
...
assertThat(actual, is(samePropertyValuesAs(expected)));

Hässlicher Fall:

import static org.hamcrest.beans.SamePropertyValuesAs.samePropertyValuesAs;
...
SomeClass expected = buildExpected(); 
SomeClass actual = sut.doSomething();

assertThat(actual.getSubObject(), is(samePropertyValuesAs(expected.getSubObject())));    
expected.setSubObject(null);
actual.setSubObject(null);

assertThat(actual, is(samePropertyValuesAs(expected)));

Also, nimm dein Gift. Zusätzliches Framework (z. B. Unitils), nicht hilfreicher Fehler (z. B. EqualsBuilder) oder flacher Vergleich (Hamcrest).

Festzelt
quelle
1
Für die Arbeit SamePropertyValuesAs müssen Sie in Projektabhängigkeit hamcrest.org/JavaHamcrest/…
bigspawn
Ich mag diese Lösung, da sie keine "völlig * andere zusätzliche Abhängigkeit" hinzufügt!
GhostCat
4

Die Bibliothek Hamcrest 1.3 Utility Matchers verfügt über einen speziellen Matcher, der Reflexion anstelle von Gleichheit verwendet.

assertThat(obj1, reflectEquals(obj2));
Stefan Birkner
quelle
2

Einige der Reflexionsvergleichsmethoden sind flach

Eine andere Möglichkeit besteht darin, das Objekt in einen JSON zu konvertieren und die Zeichenfolgen zu vergleichen.

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;    
public static String getJsonString(Object obj) {
 try {
    ObjectMapper objectMapper = new ObjectMapper();
    return bjectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
     } catch (JsonProcessingException e) {
        LOGGER.error("Error parsing log entry", e);
        return null;
    }
}
...
assertEquals(getJsonString(MyexpectedObject), getJsonString(MyActualObject))
Avraham Shalev
quelle
2

Mit Shazamcrest können Sie Folgendes tun:

assertThat(obj1, sameBeanAs(obj2));
Leonel Sanches da Silva
quelle
Warum Shazamcrest anstelle von Hamcrest verwenden? stackoverflow.com/a/27817702/6648326
MasterJoe
1
@ MasterJoe2 Gibt in meinen Tests reflectEqualszurück, falsewenn die Objekte unterschiedliche Referenzen haben.
Leonel Sanches da Silva
1

Feld für Feld vergleichen:

assertNotNull("Object 1 is null", obj1);
assertNotNull("Object 2 is null", obj2);
assertEquals("Field A differs", obj1.getFieldA(), obj2.getFieldA());
assertEquals("Field B differs", obj1.getFieldB(), obj2.getFieldB());
...
assertEquals("Objects are not equal.", obj1, obj2);
EthanB
quelle
1
Dies ist etwas, das ich nicht tun möchte, da ein früher Assert-Fehler mögliche Fehler unten verbirgt.
Ryan Nelson
2
Entschuldigung, ich habe diesen Teil Ihres Beitrags verpasst ... Warum ist ein "vollständiges Gleichheitsbild" in einer Unit-Test-Umgebung wichtig? Entweder sind alle Felder gleich (Test besteht) oder sie sind nicht alle gleich (Test schlägt fehl).
EthanB
Ich möchte den Test nicht erneut ausführen müssen, um festzustellen, ob andere Felder nicht gleich sind. Ich möchte alle ungleichen Felder im Voraus kennen, damit ich sie sofort ansprechen kann.
Ryan Nelson
1
Die Behauptung vieler Felder in einem Test würde nicht als echter "Einheitentest" angesehen. Bei der herkömmlichen testgetriebenen Entwicklung (TDD) schreiben Sie einen kleinen Test und dann nur so viel Code, dass er erfolgreich ist. Eine Behauptung pro Feld ist der richtige Weg, um dies zu tun. Setzen Sie einfach nicht alle Behauptungen in einen Test. Erstellen Sie für jede Feldbehauptung, die Sie interessiert, einen anderen Test. Auf diese Weise können Sie alle Fehler in allen Feldern mit einem einzigen Durchlauf der Suite anzeigen. Wenn dies schwierig ist, bedeutet dies wahrscheinlich, dass Ihr Code in erster Linie nicht modular genug ist und wahrscheinlich in eine sauberere Lösung umgewandelt werden kann.
Jesse Webb
Dies ist definitiv ein gültiger Vorschlag und die übliche Methode, mit der Sie mehrere Behauptungen in einem einzigen Test lösen würden. Die einzige Herausforderung hierbei ist, dass ich eine ganzheitliche Sicht auf das Objekt haben möchte. Das heißt, ich möchte alle Felder gleichzeitig testen, um sicherzustellen, dass sich das Objekt in einem gültigen Zustand befindet. Dies ist nicht schwer zu tun, wenn Sie eine überschriebene equals () -Methode haben (die ich in diesem Beispiel natürlich nicht habe).
Ryan Nelson
1

AssertJ-Assertions können verwendet werden, um die Werte zu vergleichen, ohne dass die #equalsMethode ordnungsgemäß überschrieben wird, z.

import static org.assertj.core.api.Assertions.assertThat; 

// ...

assertThat(actual)
    .usingRecursiveComparison()
    .isEqualTo(expected);
Pavel
quelle
1

Da diese Frage alt ist, werde ich einen anderen modernen Ansatz mit JUnit 5 vorschlagen.

Ich mag diese Lösung nicht, weil ich nicht das vollständige Gleichheitsbild bekomme, wenn eine frühe Behauptung fehlschlägt.

Mit JUnit 5 gibt es eine Methode namens, mit Assertions.assertAll()der Sie alle Zusicherungen in Ihrem Test zusammenfassen können. Sie führt jede aus und gibt am Ende alle fehlgeschlagenen Zusicherungen aus. Dies bedeutet, dass Zusicherungen, die zuerst fehlschlagen, die Ausführung letzterer Zusicherungen nicht stoppen.

assertAll("Test obj1 with obj2 equality",
    () -> assertEquals(obj1.getFieldA(), obj2.getFieldA()),
    () -> assertEquals(obj1.getFieldB(), obj2.getFieldB()),
    () -> assertEquals(obj1.getFieldC(), obj2.getFieldC()));
patelb
quelle
0

Sie können Reflektion verwenden, um den vollständigen Gleichheitstest zu "automatisieren". Sie können den Gleichheits-Tracking-Code implementieren, den Sie für ein einzelnes Feld geschrieben haben, und dann mithilfe von Reflection diesen Test für alle Felder im Objekt ausführen.

jtahlborn
quelle
0

Dies ist eine generische Vergleichsmethode, bei der zwei Objekte derselben Klasse auf ihre Werte für die Felder verglichen werden (beachten Sie, dass auf diese Objekte mit der Methode get zugegriffen werden kann).

public static <T> void compare(T a, T b) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
    AssertionError error = null;
    Class A = a.getClass();
    Class B = a.getClass();
    for (Method mA : A.getDeclaredMethods()) {
        if (mA.getName().startsWith("get")) {
            Method mB = B.getMethod(mA.getName(),null );
            try {
                Assert.assertEquals("Not Matched = ",mA.invoke(a),mB.invoke(b));
            }catch (AssertionError e){
                if(error==null){
                    error = new AssertionError(e);
                }
                else {
                    error.addSuppressed(e);
                }
            }
        }
    }
    if(error!=null){
        throw error ;
    }
}
Shantonu
quelle
0

Ich bin auf einen sehr ähnlichen Fall gestoßen.

Ich wollte auf einem Test vergleichen , dass ein Objekt als ein anderes die gleichen Attributwerte hatte, aber Methoden wie is(), refEq()usw. nicht funktionieren würden , aus Gründen , wie mein Objekt einen Nullwert in seinem mit idAttribute.

Das war also die Lösung, die ich gefunden habe (nun, ein Mitarbeiter hat sie gefunden):

import static org.apache.commons.lang.builder.CompareToBuilder.reflectionCompare;

assertThat(reflectionCompare(expectedObject, actualObject, new String[]{"fields","to","be","excluded"}), is(0));

Wenn der von erhaltene Wert reflectionCompare0 ist, bedeutet dies, dass sie gleich sind. Wenn es -1 oder 1 ist, unterscheiden sie sich in einigen Attributen.

Cavpollo
quelle
0

Ich hatte genau das gleiche Rätsel beim Unit-Test einer Android-App, und die einfachste Lösung, die ich gefunden habe, bestand darin, einfach Gson zu verwenden, um meine tatsächlichen und erwarteten Wertobjekte in Zeichenfolgen umzuwandeln jsonund als Zeichenfolgen zu vergleichen.

String actual = new Gson().toJson( myObj.getValues() );
String expected = new Gson().toJson( new MyValues(true,1) );

assertEquals(expected, actual);

Die Vorteile dieses über manuell zu vergleichen Feld- für -Feld ist , dass Sie vergleichen alle Ihre Felder, also auch wenn Sie später auf ein neues Feld , um es Ihre Klasse hinzufügen , wird automatisch geprüft erhalten, im Vergleich zu , wenn Sie ein Bündel wurden mit assertEquals()auf Alle Felder, die dann aktualisiert werden müssten, wenn Sie Ihrer Klasse weitere Felder hinzufügen.

jUnit zeigt auch die Zeichenfolgen für Sie an, sodass Sie direkt sehen können, wo sie sich unterscheiden. Ich bin mir nicht sicher, wie zuverlässig die Feldreihenfolge Gsonist, dies könnte jedoch ein potenzielles Problem sein.

Magnus W.
quelle
1
Die Feldbestellung wird von Gson nicht garantiert. Vielleicht möchten Sie die Zeichenfolgen JsonParse und die JsonElements vergleichen, die aus dem Parsen resultieren
Ozma
0

Ich habe alle Antworten ausprobiert und nichts hat wirklich für mich funktioniert.

Also habe ich meine eigene Methode erstellt, die einfache Java-Objekte vergleicht, ohne tief in verschachtelte Strukturen einzudringen ...

Die Methode gibt null zurück, wenn alle Felder übereinstimmen oder Zeichenfolgen enthalten, die nicht übereinstimmende Details enthalten.

Es werden nur Eigenschaften verglichen, die eine Getter-Methode haben.

Wie benutzt man

        assertNull(TestUtils.diff(obj1,obj2,ignore_field1, ignore_field2));

Beispielausgabe bei Nichtübereinstimmung

Die Ausgabe zeigt Eigenschaftsnamen und entsprechende Werte der verglichenen Objekte

alert_id(1:2), city(Moscow:London)

Code (Java 8 und höher):

 public static String diff(Object x1, Object x2, String ... ignored) throws Exception{
        final StringBuilder response = new StringBuilder();
        for (Method m:Arrays.stream(x1.getClass().getMethods()).filter(m->m.getName().startsWith("get")
        && m.getParameterCount()==0).collect(toList())){

            final String field = m.getName().substring(3).toLowerCase();
            if (Arrays.stream(ignored).map(x->x.toLowerCase()).noneMatch(ignoredField->ignoredField.equals(field))){
                Object v1 = m.invoke(x1);
                Object v2 = m.invoke(x2);
                if ( (v1!=null && !v1.equals(v2)) || (v2!=null && !v2.equals(v1))){
                    response.append(field).append("(").append(v1).append(":").append(v2).append(")").append(", ");
                }
            }
        }
        return response.length()==0?null:response.substring(0,response.length()-2);
    }
Stan Sokolov
quelle
0

Als Alternative für Nur-Junit können Sie Felder auf Null setzen, bevor die Zusicherung gleich ist:

    actual.setCreatedDate(null); // excludes date assertion
    expected.setCreatedDate(null);

    assertEquals(expected, actual);
Andrew Taran
quelle
-1

Können Sie den von Ihnen veröffentlichten Vergleichscode in eine statische Dienstprogrammmethode einfügen?

public static String findDifference(Type obj1, Type obj2) {
    String difference = "";
    if (obj1.getFieldA() == null && obj2.getFieldA() != null
            || !obj1.getFieldA().equals(obj2.getFieldA())) {
        difference += "Difference at field A:" + "obj1 - "
                + obj1.getFieldA() + ", obj2 - " + obj2.getFieldA();
    }
    if (obj1.getFieldB() == null && obj2.getFieldB() != null
            || !obj1.getFieldB().equals(obj2.getFieldB())) {
        difference += "Difference at field B:" + "obj1 - "
                + obj1.getFieldB() + ", obj2 - " + obj2.getFieldB();
        // (...)
    }
    return difference;
}

Dann können Sie diese Methode in JUnit wie folgt verwenden:

assertEquals ("Objekte sind nicht gleich", "", findDifferences (obj1, obj));

Das ist nicht klobig und gibt Ihnen vollständige Informationen über Unterschiede, falls vorhanden (durch nicht genau in der normalen Form von assertEqual, aber Sie erhalten alle Informationen, so dass es gut sein sollte).

Kamil
quelle
-1

Dies wird dem OP nicht helfen, aber es könnte allen C # -Entwicklern helfen, die hier landen ...

Wie bei Enrique veröffentlicht , sollten Sie die Methode equals überschreiben.

Gibt es eine bessere Methode, um das, was ich will, aus dem Objekt herauszuholen, ohne dass Unterklassen und Überschreibungen gleich sind (ugh)?

Mein Vorschlag ist, keine Unterklasse zu verwenden. Verwenden Sie eine Teilklasse.

Teilklassendefinitionen (MSDN)

Ihre Klasse würde also so aussehen ...

public partial class TheClass
{
    public override bool Equals(Object obj)
    {
        // your implementation here
    }
}

Für Java würde ich dem Vorschlag zustimmen, Reflektion zu verwenden. Denken Sie daran, dass Sie Reflexionen nach Möglichkeit vermeiden sollten. Es ist langsam, schwer zu debuggen und in Zukunft noch schwieriger zu warten, da IDEs Ihren Code durch eine Feldumbenennung oder ähnliches beschädigen könnten. Achtung!

Jesse Webb
quelle
-1

Von Ihren Kommentaren bis zu anderen Antworten verstehe ich nicht, was Sie wollen.

Nehmen wir nur zur Diskussion an, die Klasse hat die Methode equals überschrieben.

Ihr UT sieht also ungefähr so ​​aus:

SomeType expected = // bla
SomeType actual = // bli

Assert.assertEquals(expected, actual). 

Und du bist fertig. Darüber hinaus können Sie nicht das "vollständige Gleichheitsbild" erhalten, wenn die Behauptung fehlschlägt.

Soweit ich weiß, sagen Sie, dass Sie sich nicht dafür interessieren würden, selbst wenn der Typ gleich überschreiben würde, da Sie das "vollständige Gleichheitsbild" erhalten möchten. Es macht also auch keinen Sinn, Gleiches zu erweitern und zu überschreiben.

Sie müssen also Optionen haben: entweder Eigenschaft für Eigenschaft vergleichen, mithilfe von Reflexion oder fest codierten Prüfungen, ich würde letztere vorschlagen. Oder: Vergleichen Sie lesbare Darstellungen dieser Objekte.

Sie können beispielsweise eine Hilfsklasse erstellen, die den Typ, den Sie vergleichen möchten, mit einem XML-Dokument serialisiert und dann das resultierende XML vergleicht! In diesem Fall können Sie visuell sehen, was genau gleich ist und was nicht.

Dieser Ansatz gibt Ihnen die Möglichkeit, das Gesamtbild zu betrachten, ist jedoch auch relativ umständlich (und zunächst ein wenig fehleranfällig).

Vitaliy
quelle
Es ist möglich, dass mein Begriff "volles Gleichstellungsbild" verwirrend ist. Die Implementierung von equals () würde das Problem tatsächlich lösen. Ich bin daran interessiert, alle ungleichen Felder (die für die Gleichheit relevant sind) gleichzeitig zu kennen, ohne den Test erneut ausführen zu müssen. Die Serialisierung des Objekts ist eine weitere Möglichkeit, aber ich brauche nicht unbedingt eine tiefe Gleichheit. Wenn möglich, möchte ich die equals () - Implementierungen der Eigenschaften verwenden.
Ryan Nelson
Toll! Sie können auf jeden Fall die Gleichheit der Eigenschaften verwenden, wie Sie in Ihrer Frage angegeben haben. Es scheint, dass dies in diesem Fall die einfachste Lösung ist, aber wie Sie bemerkt haben, kann der Code sehr böse sein.
Vitaliy
-3

Sie können die equals-Methode der Klasse wie folgt überschreiben:

@Override
public int hashCode() {
    int hash = 0;
    hash += (app != null ? app.hashCode() : 0);
    return hash;
}

@Override
public boolean equals(Object object) {
    HubRule other = (HubRule) object;

    if (this.app.equals(other.app)) {
        boolean operatorHubList = false;

        if (other.operator != null ? this.operator != null ? this.operator
                .equals(other.operator) : false : true) {
            operatorHubList = true;
        }

        if (operatorHubList) {
            return true;
        } else {
            return false;
        }
    } else {
        return false;
    }
}

Wenn Sie zwei Objekte aus einer Klasse vergleichen möchten, müssen Sie die Methode equals und die Hash-Code-Methode auf irgendeine Weise implementieren

Enrique San Martín
quelle
3
aber OP sagt, dass er nicht gleich überschreiben will, er will einen besseren Weg
Ankur