IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Java Discussion :

Java reflect- égalite de deux objets Java


Sujet :

Langage Java

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 11
    Points : 3
    Points
    3
    Par défaut Java reflect- égalite de deux objets Java
    Bonjour :

    Je cherche à réaliser à l'aide de Java reflect l'égalité de 2 Object Java .
    Comment réaliser un equals() en profondeur sur des Collections/List ...
    (et par le meme temps éviter le unchecked classe exception)

  2. #2
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Salut,


    Les Collections/List implémentent déjà la méthode equals()...
    Après reste à savoir ce que tu entends par "en profondeur" !

    a++

  3. #3
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 552
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 552
    Points : 21 608
    Points
    21 608
    Par défaut
    Par ailleurs, c'est quoi, ça, "unchecked class exception" ?
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  4. #4
    Candidat au Club
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 11
    Points : 3
    Points
    3
    Par défaut

    Ce que je voudrais faire par exemple en Java reflect c'est comparer si deux object Customer sont égaux
    . (c'est à dire je voudrais comparer la valeur de name, des chacun des éléments de List<Item>,List<Waranty> etc ...)



    Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    class Customer(){
    private String name;
    List<Item> items;
    }
     
    class Item(){
    int quantite;
    float price;
    List<Waranty> waranty;
    }
     
    class waranty(){
    String name;
    int duration;
    String price;
    }

  5. #5
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Il ne faut pas passer par l'API de reflection, mais implémenter les méthodes hashCode()/equals()...



    Pourquoi et comment redéfinir la méthode equals() ?
    Pourquoi et comment redéfinir la méthode hashCode() ?

    a++

  6. #6
    Candidat au Club
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 11
    Points : 3
    Points
    3
    Par défaut
    • et tu fais ca comment pour analyser N sous List<?>

  7. #7
    Candidat au Club
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 11
    Points : 3
    Points
    3
    Par défaut
    en utilisant le BeanWrapper de Spring ca pourrait marcher ?

  8. #8
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Citation Envoyé par artaud1 Voir le message
    • et tu fais ca comment pour analyser N sous List<?>

    Si les éléments de la liste implémentent correctement equals et ahshcode (voir message d'adiguba)


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    liste1.equals(liste2)   // compare si les listes on les mêmes éléments dans le même ordre
    liste1.containsAll(liste2)   // s'assure que tous les éléments de liste2 sont dans liste 1
    liste1.containsAll(liste2) &&  liste2.containsAll(liste1) // les listes sont les même à l'ordre et la quantité près
    La reflection, oubliez, c'est bien souvent utilisé à tord et à travers par des gens qui ne veulent pas utiliser ce que les apis leur fournissent déjà.

    Vous implémentez equals et hashcode dans votre Customer, vous pourrez alors tester leur égalité.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     
    class Customer(){
    private String name;
    List<Item> items;
    public boolean equals(Object o){
       if (o instanceof Customer){
          Customer c = (Customer) o;
          return c.name.equals(name) && c.items.equals(items);
       }
       return false;
    }
    public int hashCode(){
       return name.hashCode() ^ items.hashCode();
    }
     
    }
    //etc

  9. #9
    Expert éminent sénior Avatar de Uther
    Homme Profil pro
    Tourneur Fraiseur
    Inscrit en
    Avril 2002
    Messages
    4 562
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Tourneur Fraiseur

    Informations forums :
    Inscription : Avril 2002
    Messages : 4 562
    Points : 15 502
    Points
    15 502
    Par défaut
    Citation Envoyé par artaud1 Voir le message
    • et tu fais ca comment pour analyser N sous List<?>
    equals() et hashcode() étant de la classe Object, je ne vois pas le problème.

  10. #10
    Candidat au Club
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 11
    Points : 3
    Points
    3
    Par défaut
    en gros il faudrait liste tous les champs primitifs et faire un equals dessus ... c'est assez lourd si j'ai des très gros bean .
    Pas un autre moyen + industrielle?

    Je ne veux pas écrire dans la classe Customer.
    Je souhaiterais un classe générique .

  11. #11
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par artaud1 Voir le message
    en gros il faudrait liste tous les champs primitifs et faire un equals dessus ...
    Sauf que rien ne garantie que les champs primitifs soient bien concernée par l'égalité des objets sans connaitre précisément l’implémentation de l'objet.

    a++

  12. #12
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Citation Envoyé par artaud1 Voir le message
    en gros il faudrait liste tous les champs primitifs et faire un equals dessus ...
    Les IDEs ont un petit menu 'generate equals and hashcode from fields' pour faire ça a ta place.
    Il y a aussi lombok qui permet de générer automatiquement lors de la compilation les getters, setters, equals, hashcode et toString.
    c'est assez lourd si j'ai des très gros bean .
    Pas un autre moyen + industrielle?

    Je ne veux pas écrire dans la classe Customer.
    Je souhaiterais un classe générique .
    Si je suis bien, parce que t'a pas envie d'écrire deux méthodes dans "Customer", ce qui prend 30 secondes avec un IDE, tu veux un moche truc intenable qui utilise la reflection et donc va a tous les coup ajouter dans la comparaison des champs non nécessaires.... Et qui plus est sera incompatible avec les apis existantes puisque ces dernière supposent que tu implémente correctement equals et hashCode....

  13. #13
    Candidat au Club
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 11
    Points : 3
    Points
    3
    Par défaut
    Tu pourrais tres bien avoir <T> la classe de ton objet

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    class CompareProcessor implements Comparator<T>(){
      compare(T o1, T o2) {
         //pour tous les champs pr comparer les o1.getXXX o2.getXX
     
         //pour toutes les listes objet comparer si tous les elements sont bien la .:ccool:
      }
    }
    Du coup pour traiter la partie "pour tous les champs pr comparer les o1.getXXX o2.getXX" on pourrait utiliser Java reflect ?

  14. #14
    Candidat au Club
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 11
    Points : 3
    Points
    3
    Par défaut
    Citation Envoyé par tchize_ Voir le message
    Les IDEs ont un petit menu 'generate equals and hashcode from fields' pour faire ça a ta place.
    Il y a aussi lombok qui permet de générer automatiquement lors de la compilation les getters, setters, equals, hashcode et toString.


    Si je suis bien, parce que t'a pas envie d'écrire deux méthodes dans "Customer", ce qui prend 30 secondes avec un IDE, tu veux un moche truc intenable qui utilise la reflection et donc va a tous les coup ajouter dans la comparaison des champs non nécessaires.... Et qui plus est sera incompatible avec les apis existantes puisque ces dernière supposent que tu implémente correctement equals et hashCode....
    Tout simplement parce que j'ai pas le droit de touché les "beans Data" donc pas le droit d'ecrire ces 2 methodes avec IDE
    sajoute à cela que certains de ces beans sont generes avec jaxb ...via xjc

  15. #15
    Candidat au Club
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 11
    Points : 3
    Points
    3
    Par défaut
    Citation Envoyé par artaud1 Voir le message
    Tout simplement parce que j'ai pas le droit de touché les "beans Data" donc pas le droit d'ecrire ces 2 methodes avec IDE
    sajoute à cela que certains de ces beans sont générés avec jaxb ...via xjc

  16. #16
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Citation Envoyé par artaud1 Voir le message
    J'ai pas le droit de toucher les "beans Data" donc pas le droit d'ecrire ces 2 methodes avec IDE
    Va pendre l'architecte / analyste qui t'as dit ça.

    Sinon tu as commons lang avec son EqualsBuilder.reflectionEquals() qui fait ton boulot, mais en général ca se casse les dents parce que t'as justement des champs privés dans le data que t'as pas vu et qui ne doivent pas jouer dans l'égalité, mais la reflection les utilise. Et le jour où les beans data changeront un tout petit peu, la reflection va t'exploser à la figure.

  17. #17
    Candidat au Club
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 11
    Points : 3
    Points
    3
    Par défaut
    Tas la problematique ..." progiciels" ;-) d'ou tas pas la main dessus ..
    J'ai deja essayer EqualsBuilder.reflectionEquals() ca ne passe pas à cause des champs private...

    Voila mon code en utilisant Java reflect pour les champs primitifs.
    Manque la reflections ...Pour les types Complexes type Liste et Collections
    comment faire ?

    Est ce que un containsAll suffirait ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
     
    public static <T, Y> Boolean EgalityFields(T from, Y too) {
     
    		Field[] fromFields = from.getClass().getDeclaredFields();
    		Field[] tooFields = too.getClass().getDeclaredFields();
     
     
    		//permet acceder aux champs private .
    		AccessibleObject.setAccessible(fromFields, true);
    		AccessibleObject.setAccessible(tooFields, true);
     
    		if (fromFields != null && tooFields != null) {
    			for(Field f : too.getClass().getDeclaredFields()){
    				try {
    					f.setAccessible(true);
     
    					Object temp2 = f.get(too);
    					for (Field fromTemp : fromFields) {
    						debug = fromTemp.getName();
     
    						fromTemp.setAccessible(true);
     
    						//Name variable match
    						if(fromTemp.getName().equals(f.getName()) && fromTemp.getClass().isAssignableFrom(f.getClass())){
    							Type t = fromTemp.getGenericType();
    							System.out.println("==> Type Pojo :"+fromTemp.getGenericType()+"  Declaring Type : "+fromTemp.getDeclaringClass()+"  Type : "+fromTemp.getType());
     
    							//Gere les types primitifs .
    							if(!fromTemp.get(from).equals(f.get(too))){
    								return false ;
    							}
    						}
    					}
    				}
    				catch (Exception e) {
    					e.printStackTrace();
    				}
    			}//end of loop
     
    		}
    }

  18. #18
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Citation Envoyé par artaud1 Voir le message
    J'ai deja essayer EqualsBuilder.reflectionEquals() ca ne passe pas à cause des champs private...
    Et pourtant, d'après la javadoc:
    public static boolean reflectionEquals(Object lhs,
    Object rhs)

    This method uses reflection to determine if the two Objects are equal.

    It uses AccessibleObject.setAccessible to gain access to private fields.
    Est ce que un containsAll suffirait ?
    containsAll, equals, etc. Tout ce ne marchera pas correctement si les éléments à l'intérieur n'implémentent pas correctement equals/hashcode. Vous pouvez parcourir les liste à la main et comparer les champs.

    PS: cette déclaration me semble incorrect:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    public static <T, Y> Boolean EgalityFields(T from, Y too)
    Si les objets n'ont pas un type commun, ca n'a pas de sens de les comparer:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    public static <T> Boolean EgalityFields(T from, T too)
    Un customer n'est pas un item.

    Enfin, tout l'idée de l'api reflection est, a mon avis, mal partie. Si vous n'avez pas accès aux objet, utilisez les getters/setters des objets pour déterminer si ils sont égaux. C'est bien plus propre, ne nécessite pas de bidouille du securitymanager et risque mois de vous exploser à la figure.

  19. #19
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par tchize_ Voir le message
    Enfin, tout l'idée de l'api reflection est, a mon avis, mal partie.
    +1

    En plus selon le cas cela ne marche pas forcément même avec des types "basiques" comme String...


    a++

  20. #20
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    je verrais plutot ce genre de code, plus propre. Et bien plus rapide à coder que la prise de tete reflection

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
     
    // pour les types de base comme String, Integer, etc
    public static boolean equals(Object a, Object b){
        if ((a==null) && (b==null))
          return true;
        if (a==null  ||b == null)
          return false;
        return a.equals(b);
    }
    // Testeur de collection, ne supporte pas les boucle du style customer -> items -> vendor -> customers
     
    public static <T> boolean equalsCollection(Collection<T> a, Collection<T> b, EqualTester<T> equalTester) {
        if (a==null && b==null)
            return true;
        if (a==null ||b ==null)
            return false;
        if (a.size()!=b.size())
            return false;
        Iterator<T> ta = a.iterator();
        Iterator<T> tb = b.iterator();
        while (ta.hasNext())
            if (!equalTester.isEquals(ta.next(),tb.next()))
               return false;
        return true;
    }
    // teste deux customers
    public static boolean equals(Customer a, Customer b){
       return equals(a.getName(),b.getName()) &&
           equals(a.getLastname(),b.getLastname()) &&
           equals(a.getPhone(),b.getPhone())&&
           equals(a.getAddresse(),b.getAddresse()) &&
           equals(a.getItems(),b.getItems(),Item.class, new EqualTester<Item>(){
                   public boolean isEquals(Item a,Item b) {return equals(a,b);}
           }) ;
    }
    public static boolean equals(Adresse a, Adresse b){
    //todo
    }
    public static boolean equals(Item a, Item b){
    //todo
    }
    }
    Avec au moins l'avantage qu'on vois tout de suite quels sont vos critères.

Discussions similaires

  1. Tester l'égalité de deux objets Range
    Par ANOVA dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 07/06/2010, 15h11
  2. Echange d'objet java entre deux applications
    Par m3allem001 dans le forum Langage
    Réponses: 3
    Dernier message: 03/04/2009, 13h20
  3. [Excel][VBA][Java] Appeler un objet java
    Par ay_pepito dans le forum Macros et VBA Excel
    Réponses: 5
    Dernier message: 29/07/2005, 15h46
  4. [Java] Héritage et flux d'Objet
    Par guejo dans le forum CORBA
    Réponses: 2
    Dernier message: 22/02/2005, 11h14
  5. [SAX] Passer d'objet java en fichier XML?
    Par spoutyoyo dans le forum Format d'échange (XML, JSON...)
    Réponses: 15
    Dernier message: 05/01/2005, 08h31

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo