2009-01-23 14 views
15

Próbowałem grok bibliotekę org.apache.commons.beanutils dla metody/idiomu do oceny równości czyli generyczne równi() Metoda wszystkie właściwości między 2 przypadkach na fasoli.
Czy istnieje prosty sposób na wykonanie tej czynności przy użyciu tej biblioteki? Czy robię to niewłaściwie? Dzięki.jak ogólnie porównać całe fasole java?

+0

W tym kontekście może zainteresować się biblioteka [xtendbeans library] (http://stackoverflow.com/a/39222891/421602); zobacz [pełny przykład na temat tego drugiego pytania SO] (http://stackoverflow.com/a/39222891/421602). – vorburger

Odpowiedz

16

Spróbuj EqualsBuilder.reflectionEquals() z commons-lang. EqualsBuilder ma zestaw metod obejmujących wszystkie pola, wszystkie nieprzechodnie pola i wszystkie oprócz określonych pól.

Jeśli wszystko inne zawiedzie, kod może służyć jako dobry przykład jak zaimplementować to.

+3

Należy pamiętać, że nie jest to rekursywne - więc jeśli masz zagnieżdżone komponenty bean (tj. Właściwość komponentu bean to kolejna fasola), trzeba same wprowadzić równych sobie. Parametr 'reflectionEquals' po prostu wywołuje' equals' na każdej właściwości, ale nie odzwierciedla on jeszcze klasy. – artbristol

+1

@artbristol: +1, ale bądź ostrożny, rekurencyjny będzie równy: Możesz łatwo zostać złapanym w pętlę, gdy cykle tworzą się. –

7

Aby odpowiedzieć na to pytanie bezpośrednio, można użyć refleksji zrobić równości sprawdzanie fasoli. Jest kilka przeszkód, o których musisz wiedzieć.

Istnieją zasady dotyczące zachowania równych() i hashcode(). Przepisy te mówią o symetrii consitency i reflexiveness, które mogą być trudne do zrobienia, gdy metoda equals zachowuje się dynamicznie na podstawie innego obiektu jesteś przechodzącą w

ciekawe brzmienie. http://www.geocities.com/technofundo/tech/java/equalhash.html

Ogólnie rzecz biorąc, myślę, lepiej jest tworzyć własny kod dostępu i równać się metodom. Istnieje kilka dobrych wtyczek, które mogą automatycznie wygenerować ten kod w oparciu o właściwości klasy.

Powiedziawszy to wszystko, oto kilka (stary styl) metody coraz pobierające, ustawiające i właściwości napisałem dawno temu:

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

W pobierające:

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

A Setery:

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

Może możesz użyć tego do rzucenia własnego.

Edit: Oczywiście reflectionbuilder w Aaron Digulla's answer jest o wiele lepszy niż mój rozpostarcie.

+0

metody pobierające boolean są nazywane isFoo(), więc kod będzie wymagał niewielkiego rozszerzenia w getGetters() –

2

Jak wspomniano powyżej, realizacja odbiciem oparte będą robić to, co chcesz. Chciałem tylko ostrzec, że refleksja jest dość kosztowna i taka implementacja może być stosunkowo powolna. Jeśli potrzebujesz tylko okazyjnych porównań, wszystko będzie dobrze. Jeśli jednak masz duże zbiory danych i częste kontrole równości (np. Filtrowanie dużych tabel), możesz mieć kłopoty.

+0

Dobra uwaga. jguru ma ładne porównanie online: http://www.jguru.com/faq/view.jsp?EID=246569 – Rolf

0

Albo, chociaż nie bezpośredni odpowiedź na swoje pytanie, ale może to być odpowiedź na Twój problem (czyli usunąć wysiłek robi kod szablonowe podczas będąc super fast)

jeśli używasz Eclipse, następujące kroki automatycznego generowania hashCode i równa dla Ciebie:

Źródło> Generuj hashCode i równa ...

a następnie wybrać pola, to bardzo skuteczne!: D

Pozdrawiam i mam nadzieję, że pomoże to każdemu, kto tu przyjedzie, w celu skrócenia czasu pisania na tablicy.

PS: Jestem pewien, że inne popularne IDE muszą mieć podobne funkcje.