2009-01-23 4 views
15

J'ai essayé de grok la bibliothèque org.apache.commons.beanutils pour une méthode/idiome pour évaluer l'égalité toutes les propriétés entre 2 instances, c'est-à-dire une méthode générique equals() pour les beans.
Existe-t-il un moyen simple de faire ceci usnig cette bibliothèque? Ou est-ce que je vais à ce sujet dans le mauvais sens? Merci.comment comparer génériquement des grains entiers de Java?

+0

La [bibliothèque xtendbeans] (http://stackoverflow.com/a/39222891/421602) pourrait être intéressante dans ce contexte; voir [l'exemple complet plus sur cette autre question SO] (http://stackoverflow.com/a/39222891/421602). – vorburger

Répondre

16

Essayez EqualsBuilder.reflectionEquals() de commons-lang. EqualsBuilder a un ensemble de méthodes pour inclure tous les champs, tous les champs non transitoires et tous les champs sauf certains.

Si tout le reste échoue, le code pourrait servir comme un bon exemple comment implémenter cela.

+3

Soyez averti que ce n'est pas récursif - donc si vous avez des beans imbriqués (ie une propriété d'un bean est un autre bean), besoin de mettre en œuvre est égal à eux-mêmes. "reflectionEquals" appelle juste "equals" sur chaque propriété, il ne réfléchit plus dans la classe. – artbristol

+1

@artbristol: +1 mais attention, récursive est égale à: Vous pouvez facilement être pris dans une boucle lorsque les haricots forment des cycles. –

7

Pour répondre directement à votre question, vous pouvez utiliser la réflexion pour faire un contrôle d'égalité des haricots. Il y a quelques problèmes dont vous devez être conscient.

Il existe des règles concernant le comportement de equals() et hashcode(). Ces règles parlent de symétrie, consitency et réflexivité qui peut être difficile à faire lorsque votre méthode equals se comporte dynamiquement en fonction de l'autre objet que vous passer dans

lecture intéressante. http://www.geocities.com/technofundo/tech/java/equalhash.html

D'une manière générale, je pense vous feriez mieux de créer votre propre code et équivaut à des méthodes. Il existe un bon plugin fwe qui peut automatiquement générer ce code pour vous en fonction des propriétés de la classe.

Après avoir dit tout cela, voici quelques méthodes pour obtenir getters, setters et propriétés (style ancien) j'ai écrit il y a longtemps:

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; 
} 

getters:

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; 
} 

Et la setters:

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; 
} 

peut-être que vous pouvez utiliser pour rouler votre propre.

Editer: Bien sûr, le reflectionbuilder dans Aaron Digulla's answer est beaucoup mieux que mon handywork.

+0

Les getters booléens sont appelés isFoo(), donc le code aurait besoin d'une petite amélioration dans getGetters() –

2

Comme mentionné ci-dessus, une implémentation basée sur la réflexion fera ce que vous voulez. Je voulais juste vous avertir, que la réflexion est très coûteuse et qu'une telle mise en œuvre pourrait être comparativement lente. Si vous avez juste besoin de faire des comparaisons occasionnelles, tout ira bien. Cependant, si vous avez d'énormes ensembles de données et des contrôles d'égalité fréquents (par exemple, le filtrage de grandes tables), vous risquez de rencontrer des problèmes.

+0

Bon point en effet. jguru a une belle comparaison en ligne: http://www.jguru.com/faq/view.jsp?EID=246569 – Rolf

0

Ou, mais pas une réponse directe à votre question, mais il pourrait être une réponse à votre problème (c.-à supprimer l'effort de faire le code boilerplate tout étant super rapide)

si vous utilisez Eclipse, la étapes suivantes génère automatiquement le code de hachage et égale pour vous:

Source> générer hashCode et égaux ...

puis sélectionnez les champs, il est super efficace!: D

Salutations et j'espère que cela aidera ceux qui viennent ici dans le but de faire un peu de temps à écrire des documents. PS: Je suis sûr que d'autres IDE populaires doivent avoir des caractéristiques similaires.

Questions connexes