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 :

Generics et Comparator


Sujet :

Langage Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Rédacteur
    Avatar de benwit
    Profil pro
    dev
    Inscrit en
    Septembre 2004
    Messages
    1 676
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : dev

    Informations forums :
    Inscription : Septembre 2004
    Messages : 1 676
    Par défaut Generics et Comparator
    Bonjour,

    J'ai le code suivant :
    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
     
    @SuppressWarnings("unchecked")
    @Override public int compare(Data d1, Data d2)
    {
        Comparable<?> c1 = (d1 != null)? d1.getField(sortFieldId) : null;
        Comparable<?> c2 = (d2 != null)? d2.getField(sortFieldId) : null;
     
        if (c1 == null)
            return -1;
     
        if (c2 == null)
            return 1;
     
        if (sortAsc)
            return ((Comparable)c1).compareTo((Comparable) c2);
        else
            return ((Comparable)c2).compareTo((Comparable)c1);
    }
    Je dois comparer les champs (c1 et c2) de deux objets de données (d1 et d2).
    J'ai écrit un truc qui fonctionne (en virant les warnings sur les 2 derniers return par @SuppressWarnings("unchecked")).
    Bon, ça fonctionne car c1 et c2 sont toujours du même type et sont toujours des objets comparables (ex Comparable<String>, Comparable<Integer> ...)

    Seulement, je ne trouve pas ceci très élégant !

    Alors, je demande à ceux qui maitrisent les generics s'il y a une manière plus propre d'écrire cela ?

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

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

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    Je part du principe que getField retourne un Comparable<?>. C'est en fait là que se trouve le problème Il faudrait que la valeur de retour soit plus typée pour pouvoir l'utiliser. L'ennui c'est que, je suppose, suivant l'index, t'as pas la moindre idée du type de comparable.... Tu peux peut être essayer avec Comparable<? extends Object> mais je suis pas convaincu.... Tu risque de devoir te coltiner les warning. Note que, si tu regarde la source de ArrayList, tu verra que sun se coltine aussi pas mal de suppressWarning

  3. #3
    Rédacteur
    Avatar de benwit
    Profil pro
    dev
    Inscrit en
    Septembre 2004
    Messages
    1 676
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : dev

    Informations forums :
    Inscription : Septembre 2004
    Messages : 1 676
    Par défaut
    Oui, getField retourne un Comparable<?>
    et oui, j'ai pas la moindre idée du type de comparable, parfois c'est Comparable<String>, d'autre fois Comparable<Integer>, ...

    J'ai également essayé Comparable<? extends Object> mais pas mieux ...
    soit des warnings, soit des erreurs ...

    J'ai également pensé à la possibilité de passer le type de comparable à la méthode getField() mais je ne sais pas trop comment m'y prendre ?

    si tu regarde la source de ArrayList, tu verra que sun se coltine aussi pas mal de suppressWarning
    Je sais pas si c'est inquiétant ou rassurant

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

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

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    C'est juste pas toujours possible de dire au compilo que "c'est correct, çà marchera" -> le suppress warning. Si on en avait pas besoin sun l'aurais pas inventé :p


    Pour passer le type de comparable, tu peux faire:

    Comparable<T> getField(int column, Class<T> type){..........}

    Mais tu risque de déplacer ton problème dans getField() (à voir dans son code si c'est possible....)

  5. #5
    Expert éminent
    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
    Billets dans le blog
    1
    Par défaut
    Salut,

    Perso un @SuppressWarning ne me dérange pas dans ce cas là...


    L'objectif des Generics est de vérifier le type des éléments à la compilation, afin de fournit un code typesafe. C'est à dire qu'un code Generics qui compile sans warnings ne générera pas de ClassCastException.

    Ici tu utilises un type inconnu : en lisant le code de ta méthode compare() on ne peut pas déterminer le typage de tes objets Comparable, et du coup on ne peut pas garantir que les deux types soit compatible...

    Le compilateur ne peut pas s'assurer de la légitimité du code, et génère donc un warning pour le signaler. En utilisant @SuppressWarning tu indiques donc au compilateur que tu prends à ton compte la responsabilité de la cohérence du typage...


    Par contre je te conseillerais d'utiliser une méthode private qui contiendra le code unsafe, et de n'utiliser le @SuppressWarning que sur ce code. Ceci afin d'éviter de cacher d'autres warnings sans le vouloir...



    Sinon il pourrait être intéressant de voir le code de la méthode getField()...


    a++

  6. #6
    Rédacteur
    Avatar de benwit
    Profil pro
    dev
    Inscrit en
    Septembre 2004
    Messages
    1 676
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : dev

    Informations forums :
    Inscription : Septembre 2004
    Messages : 1 676
    Par défaut
    Merci pour vos réponses,

    Citation Envoyé par adiGuba Voir le message
    Salut,
    En utilisant @SuppressWarning tu indiques donc au compilateur que tu prends à ton compte la responsabilité de la cohérence du typage...
    Oui, c'est ça, je prend la responsabilité !

    Citation Envoyé par adiGuba Voir le message
    Sinon il pourrait être intéressant de voir le code de la méthode getField()...
    Rien de bien folichon, juste un retour d'une String (qui implemente Comparable<String>), un retour d'Integer (qui implemente Comparable<Integer>), etc ... bref, des retours de type simples pour commencer ... voir peut être des retours de certains de mes objets qui implémenteront Comparable.

    Mais comme le dit tchize_, je risque donc de déplacer mon problème ...


    Sinon, tant qu'on est à discuter des comparables et des generics, il y a deux points qui pourraient être améliorés dans le JDK (à moins que ce ne soit pas possible ??? mais pourquoi ?) :

    Premièrement, pourquoi, alors que Integer, Long, Double et Float dérivent de Number, cette dernière n'est pas Comparable<Number> ?

    Deuxièmement, pourquoi les objets de types simples + String + éventuellement Date n'implémentent pas une interface "SimpleType". Je suis d'accord que dans de nombreux cas, c'est un problème de conception (sinon ce n'est plus la peine de faire du typage static) mais il y a toujours quelque rare cas où ça m'arrangerait. A part Object, je n'ai trouvé que Serializable comme point commun mais ça reste un peu trop fourre tout à mon goût. La seule autre manière plus propre que j'ai trouvé est de faire des "Adapter" pour les types simples, mais ça fait une encapsulation de plus

    Qu'en pensez vous ?

  7. #7
    Expert éminent
    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
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par benwit Voir le message
    Rien de bien folichon, juste un retour d'une String (qui implemente Comparable<String>), un retour d'Integer (qui implemente Comparable<Integer>), etc ... bref, des retours de type simples pour commencer ... voir peut être des retours de certains de mes objets qui implémenteront Comparable.
    Disons que s'il y a une possibilité pour faire un code 100% Generics, cela passera par là... donc il aurait été intéressant de la voir

    Maintenant si tu utilises la reflection il y a de forte chance que tu doivent quand même passer par un @SupressWarning...


    Citation Envoyé par benwit Voir le message
    Premièrement, pourquoi, alors que Integer, Long, Double et Float dérivent de Number, cette dernière n'est pas Comparable<Number> ?
    Car les Generics n'implémentent pas un tel héritage qui peut aboutir à des états incohérents.
    Par exemple si ce code compilait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    	Integer integerObject = new Integer(0);
    	Double doubleObject = new Double(0.0);
     
    	Comparable<Number> comparable =  integerObject; // ERREUR
     
    	comparable.compareTo(doubleObject);
    On appellerait compareTo(Integer) avec un Double !
    Bref on se retrouverait dans des cas incorrects qui génèreraient des erreurs à l'exécution, et c'est exactement ce que les Generics sotn cencé combattre


    Citation Envoyé par benwit Voir le message
    Deuxièmement, pourquoi les objets de types simples + String + éventuellement Date n'implémentent pas une interface "SimpleType". Je suis d'accord que dans de nombreux cas, c'est un problème de conception (sinon ce n'est plus la peine de faire du typage static) mais il y a toujours quelque rare cas où ça m'arrangerait. A part Object, je n'ai trouvé que Serializable comme point commun mais ça reste un peu trop fourre tout à mon goût. La seule autre manière plus propre que j'ai trouvé est de faire des "Adapter" pour les types simples, mais ça fait une encapsulation de plus
    Tu veux faire quoi exactement ?


    a++

Discussions similaires

  1. Generics Comparable <T>
    Par mafanta dans le forum Langage
    Réponses: 9
    Dernier message: 15/11/2011, 11h34
  2. Generics, Comparable et classes abstraites
    Par Bowbaq dans le forum Langage
    Réponses: 2
    Dernier message: 27/03/2010, 01h48
  3. [LG][FAQ]comparer des fichiers
    Par lucke dans le forum Langage
    Réponses: 11
    Dernier message: 01/06/2003, 18h02
  4. [langage] Comparer Perl avec d'autres langages comme C ?
    Par Anonymous dans le forum Langage
    Réponses: 3
    Dernier message: 10/08/2002, 23h52
  5. Comparer des fichiers de données : Quel Langage ?
    Par Anonymous dans le forum Langages de programmation
    Réponses: 6
    Dernier message: 24/04/2002, 22h37

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