2009-01-23 13 views
15

Ich habe versucht, die org.apache.commons.beanutils Bibliothek für eine Methode/Idiom, um für die Gleichheit alle Eigenschaften zwischen 2 Instanzen, das heißt eine generische equals() -Methode für Beans zu grok.
Gibt es eine einfache Möglichkeit, dies usnig diese Bibliothek zu tun? Oder mache ich das falsch? Danke.Wie generiere ich ganze Java-Bohnen?

+0

Die [Xtendbeans-Bibliothek] (http://stackoverflow.com/a/39222891/421602) könnte in diesem Zusammenhang von Interesse sein; siehe [das vollständige Beispiel zu dieser anderen SO-Frage] (http://stackoverflow.com/a/39222891/421602). – vorburger

Antwort

16

Versuchen Sie EqualsBuilder.reflectionEquals() von commons-lang. EqualsBuilder verfügt über eine Reihe von Methoden, um alle Felder, alle nicht vorübergehenden Felder und alle bis auf bestimmte Felder einzuschließen.

Wenn alles andere fehlschlägt, könnte der Code als ein gutes Beispiel dafür dienen, dies zu implementieren.

+3

Seien Sie gewarnt, dass dies nicht rekursiv ist - also wenn Sie geschachtelte Beans haben (dh eine Eigenschaft einer Bean ist eine andere Bean) müssen sich selbst umsetzen. 'reflectionEquals' ruft auf jeder Eigenschaft nur" equals "auf, es spiegelt sich in der Klasse nicht weiter. – artbristol

+1

@artbristol: +1 aber seien Sie vorsichtig rekursiv gleich: Sie können leicht in einer Schleife gefangen werden, wenn Bohnen Zyklen bilden. –

7

Um Ihre Frage direkt zu beantworten, können Sie Reflektion verwenden, um die Gleichheitsprüfung von Beans durchzuführen. Es gibt ein paar Haken, die Sie beachten müssen.

Es gibt Regeln bezüglich des Verhaltens von equals() und hashcode(). Diese Regeln sprechen über Symmetrie, consitency und Reflexivität, die nur schwer zu tun, wenn Ihre Methode equals dynamisch auf dem anderen Objekt basiert verhält Sie vorbei in

interessant zu lesen:. http://www.geocities.com/technofundo/tech/java/equalhash.html

Allgemein gesprochen, ich glaube, Sie erstellen besser Ihren eigenen Hashcode und gleichen Methoden. Es gibt ein paar gute Plugins, die basierend auf den Klasseneigenschaften automatisch diesen Code für Sie generieren können.

all dies gesagt ist, sind hier einige (alte) Methoden, um Getter, Setter und Eigenschaften ich vor langer Zeit schrieb:

private Map getPrivateFields(Class clazz, Map getters, Map setters) { 
    Field[] fields = clazz.getDeclaredFields(); 
    Map m = new HashMap(); 
    for (int i = 0; i < fields.length; i++) { 
     int modifiers = fields[i].getModifiers(); 
     if (Modifier.isPrivate(modifiers) && !Modifier.isStatic(modifiers) && !Modifier.isFinal(modifiers)) { 
      String propName = fields[i].getName(); 
      if (getters.get(propName) != null && setters.get(propName) != null) { 
       m.put(fields[i].getName(), fields[i]); 
      } 
     } 
    } 
    return m; 
} 

Die Getter:

private Map getGetters(Class clazz) { 
    Method[] methods = clazz.getMethods(); 
    Map m = new HashMap(); 
    for (int i = 0; i < methods.length; i++) { 
     if (methods[i].getName().startsWith("get")) { 
      int modifiers = methods[i].getModifiers(); 
      if (validAccessMethod(modifiers)) { 
       m.put(getPropertyName(methods[i].getName()), methods[i]); 
      } 
     } 
    } 
    return m; 
} 

Und die Setter:

private Map getSetters(Class clazz, Map getters) { 
    Method[] methods = clazz.getMethods(); 
    Map m = new HashMap(); 
    for (int i = 0; i < methods.length; i++) { 
     if (methods[i].getName().startsWith("set")) { 
      int modifiers = methods[i].getModifiers(); 
      String propName = getPropertyName(methods[i].getName()); 
      Method getter = (Method) getters.get(propName); 

      if (validAccessMethod(modifiers) && getter != null) { 
       Class returnType = getter.getReturnType(); 
       Class setType = methods[i].getParameterTypes()[0]; 
       int numTypes = methods[i].getParameterTypes().length; 

       if (returnType.equals(setType) && numTypes == 1) { 
        m.put(propName, methods[i]); 
       } 
      } 
     } 
    } 
    return m; 
} 

Vielleicht können Sie dies verwenden, um Ihre eigenen zu rollen.

Edit: Ofcourse die reflectionbuilder in Aaron Digulla's answer ist viel besser als meine Hände Werk.

+0

Boolesche Getter heißen isFoo(), daher müsste der Code eine kleine Verbesserung in getGetters() haben –

2

Wie oben erwähnt, wird eine reflektionsbasierte Implementierung tun, was Sie wollen. Ich wollte Sie nur warnen, dass die Reflexion ziemlich kostspielig ist und eine solche Implementierung vergleichsweise langsam sein könnte. Wenn Sie nur gelegentliche Vergleiche machen müssen, wird es Ihnen gut gehen. Wenn Sie jedoch riesige Datasets und häufige Gleichheitsüberprüfungen (z. B. Filtern von großen Tabellen) haben, könnten Sie in Schwierigkeiten geraten.

+0

Guter Punkt in der Tat. Jguru hat einen schönen Vergleich online: http://www.jguru.com/faq/view.jsp?EID=246569 – Rolf

0

Oder, wenn auch nicht eine direkte Antwort auf Ihre Frage, aber es könnte eine Antwort auf Ihr Problem (dh entfernen Sie den Aufwand vorformulierten Code zu tun während super schnell ist) sein

, wenn Sie Eclipse, die folgende Schritte werden automatisch die hashCode generieren und gleich für Sie:

Source> Generate hashCode und gleich ...

und dann die Felder auswählen, es ist super effektiv!: D

Prost und ich hoffe, es hilft wer auch immer hier mit dem Zweck kommt, einige Zeit zu schreiben schreiben Platte.

PS: Ich bin sicher, dass andere populäre IDEs ähnliche Funktionen haben müssen.