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

Collection et Stream Java Discussion :

Généricité, collections et wildcards


Sujet :

Collection et Stream Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2011
    Messages
    179
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2011
    Messages : 179
    Par défaut Généricité, collections et wildcards
    Bonjour,

    j'ai un souci de compréhension concernant les wildcards (?) et la généricité pour les collections. Je comprends bien l'utilisation du wilcard dans le cas de figure où on veut utiliser le polymorphisme pour une méthode :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    public void fonctionBidule(List<? extends Chose> list){
       ...
    }
    Par contre, je ne vois pas l'intérêt d'utiliser le wildcard pour l'initialisation ou la déclaration d'une Collection ?

    Quelle est la différence par exemple entre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    List<? extends Chose> list = new ArrayList<Chose>();
    et :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    List<Chose> list = new ArrayList<Chose>();
    Sachant que, à moins que je me trompe, dans les 2 cas de figure, on peut ajouter aux ArrayList des références à des classes ou sous classes de Chose ?

    Merci de m'aider à comprendre

  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
    ha non, dans le premier cas, on ne pourra rien ajouter, car on ne sais pas, a priori quel type concret stocke la liste

    L'intéret du premier cas et de pouvoir remplacer la liste par une autre si besoin. Exemple

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    List<? extends Chose> list = new ArrayList<Chose>();
     
    public setListe(List<? extends Chose> list){
       this.list=list
    }
    //....
    instance.setListe(new ArrayList<Bidule>());//Bidule extends Chose
    alors que si on type exactement

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    List<Chose> list = new ArrayList<Chose>();
     
    public setListe(List<Chose> list){
       this.list=list
    }
    //....
    instance.setListe(new ArrayList<Bidule>());//erreur

  3. #3
    Membre éprouvé Avatar de dev_2007
    Profil pro
    Inscrit en
    Août 2007
    Messages
    98
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Août 2007
    Messages : 98
    Par défaut
    Et je rajoute quelque intérêt des wildcard :

    - Le wildcard (?) permet de dire que n'importe quel type peut être traité et donc accepté !

    - Dès que le wildcard (?) est utilisé sur une collection, cela revient à rendre la dite collection en lecture seule !

    - L'instruction <? extends MaClasse> autorise toutes les collections de classes ayant pour super type MaClasse.

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2011
    Messages
    179
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2011
    Messages : 179
    Par défaut
    En fait, je me suis fais un petit exemple de test où j'ai crée une interface I, une classe Impl implémentant I et une classe ImplFille étendant Impl

    Ce code marche :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    List<Impl> list1 = new ArrayList<Impl>();
    list1.add(new Impl());
     
    List<ImplFille> list2 = new ArrayList<ImplFille>();
    list2.add(new ImplFille());
     
    list1.addAll(list2);
     
    List<? extends Impl> list3 = list1;

    En quoi est il différent svp de celui ci (qui marche aussi) ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    List<Impl> list1 = new ArrayList<Impl>();
    list1.add(new Impl());
    list1.add(new ImplFille());

  5. #5
    Modérateur

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

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 582
    Par défaut
    Citation Envoyé par jecomprendsrien Voir le message
    En quoi est il différent svp de celui ci (qui marche aussi) ?
    Je ne vois pas en quoi ils sont semblables. Ils sont différents en tout.

    Dans le second cas, tu as créé une seule List, contenue dans la variable list1, et elle contient deux objets.

    Dans le premier cas, tu as créé deux List, dans les variables list1 et list2, de sorte que list2 contienne un objet et list1 en contienne deux.
    Puis tu as déclaré une troisième variable list3 qui pointe vers list1.

    Dans les deux cas tu te retrouves avec une variable nommée list1, de type List<Impl> qui contient la même chose.
    À part ça, les deux cas n'ont pas de point commun. Puisqu'ils ne se ressemblent même pas, je dirais que leurs différences, c'est tout. Ils sont différents en tout. Il n'y a rien à comparer entre deux choses qui ne se ressemblent pas.

    Citation Envoyé par dev_2007 Voir le message
    - Le wildcard (?) permet de dire que n'importe quel type peut être traité et donc accepté !
    ?? Non... Il signifie qu'on ne sait pas ce que la collection contient. Par conséquent elle n'accepte aucun type (puisque quel que soit le type qu'on voudrait y mettre, on ne sait pas si c'est le bon, donc on ne peut pas.)
    Autre conséquence, ce qu'elle contient ne peut être traité que comme Object, le type parent à tous les types objets.

    Citation Envoyé par dev_2007 Voir le message
    - Dès que le wildcard (?) est utilisé sur une collection, cela revient à rendre la dite collection en lecture seule !
    Pas tout à fait. C'est le cas de <?> et de <? extends truc>. Vu qu'on ne sait pas ce que contient la collection, on ne peut rien mettre dedans, c'est logique.

    Mais avec <? super machin>, par contre, on peut y mettre des machin. Ce n'est donc pas en lecture seule.


    Citation Envoyé par dev_2007 Voir le message
    - L'instruction <? extends MaClasse> autorise toutes les collections de classes ayant pour super type MaClasse.
    Ça ne veut pas dire grand-chose, tout ça. On vient de dire qu'on ne peut rien mettre dans une collection qui fait <? extends MaClasse>.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  6. #6
    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
    d'une manière générale, quand tu utilise le wildcard <?> ou <? extends ...> dans la déclaration d'une variable ou d'un champ:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    List<? extends Truc> maListe = new ArrayList<TrucBidule>();
    Comparator<?  extends Truc> monComparator = new MonComparator();
    tu t'interdis d'appeler toute méthode prenant ce type en paramètre. Ainsi, tu ne pourra pas appeler maListe.add(T) ni monComparator.compare(T,T). Par contre, tu peux toujours appeler des méthodes qui retournent ce type car, on sais, quelle retournent au moins un Truc. Exemple: Truc t = maListe.get(0);

    List<?> est l'équivalent de List<? extends Object>. Attention aussi à l'erreur commune. Déclarer List maliste; n'est pas la même chose que déclarer List<?> maliste; Dans le premier cas on précise au compilateur (et ça génère un warning) qu'il faut ignorer toute la logique des classes génériques. Dans le second cas on lui dit qu'on ignore quel type sera utilisé. A ce titre, le premier cas est beaucoup plus proche de List<Object> maliste


    Et comme le précise theElvin, <? super ...> fonctionne dans le sens inverse: tu pourra appeler des méthodes (car tu connais des types compatibles), mais le retour seront tous de type Object au mieux

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Conversions, collections et généricité
    Par whims dans le forum Langage
    Réponses: 3
    Dernier message: 30/12/2010, 13h34
  2. Généricité et fonction Collections.sort
    Par Matthiews dans le forum Collection et Stream
    Réponses: 4
    Dernier message: 23/07/2010, 09h38
  3. Pb de conception avec collection / objet et généricité
    Par MrEddy dans le forum Général Java
    Réponses: 5
    Dernier message: 16/06/2010, 14h36
  4. Question sur la généricité et les Collections
    Par MrEddy dans le forum Général Java
    Réponses: 4
    Dernier message: 11/06/2010, 11h39
  5. HashMap, généricité, wildcard, héritage, extension
    Par kenji_getpowered dans le forum Collection et Stream
    Réponses: 2
    Dernier message: 01/04/2010, 17h40

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