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 :

Tableau de généric en retour de méthodes


Sujet :

Collection et Stream Java

  1. #1
    lvr
    lvr est déconnecté
    Membre extrêmement actif Avatar de lvr
    Profil pro
    Responsable de projet fonctionnel
    Inscrit en
    Avril 2006
    Messages
    909
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Responsable de projet fonctionnel
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Avril 2006
    Messages : 909
    Points : 1 360
    Points
    1 360
    Par défaut Tableau de généric en retour de méthodes
    Je viens de relire la faq d'Angelika Langer sur les générics, mais je n'y ai pas vu d'explication à pourquoi je reçois une erreur de compilation dans ce cas de figure:
    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 UneClasse {
       Tag[] tags=new Tag[0];
       Filler<Tag> filler=new Filler<Tag>();
     
       public dofill() {
              tags=filler.getfill();
              }  
    }   
     
    Class Filler<T> {
       ...
       public T[] getfill() {
              return ...
              }  
    }
    La compilation me retourne une erreur sur tags=filler.getfill(). Je ne comprends pas car tout coïncide, il n'y pas d'héritage, de cast foireux...

    Pour le moment, pour que ça passe sans erreurs et warning, j'ai écris cette horeur:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    tags=Arrays.asList(filler.getfill()).toArray(new Tag[0]);
    Si c'est la seule solution, c'est plutôt

    Merci.

  2. #2
    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
    Est ce que tu pourrait poster un code minimum exact permettant de reproduire ton problème, car je vois plusieurs erreurs dans le code que tu as posté (class avec une majuscule, méthode sans type de retour). Cependant la ligne que tu indiques en erreur m'a l'air bonne.

  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
    Comme dit Uther, il n'y a pas d'erreur sur la ligne indiquée.

    Mais je confirme que mêler tableaux et génériques, c'est la plaie. Il vaut mieux se baser sur Arrays.asList() et Collection.toArray(). (Mais pour passer de l'un à l'autre, pas dans la même instruction, évidemment.)
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  4. #4
    lvr
    lvr est déconnecté
    Membre extrêmement actif Avatar de lvr
    Profil pro
    Responsable de projet fonctionnel
    Inscrit en
    Avril 2006
    Messages
    909
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Responsable de projet fonctionnel
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Avril 2006
    Messages : 909
    Points : 1 360
    Points
    1 360
    Par défaut
    A la demande générale, voici le code incriminé:
    1) Le composant Swing avec Generic
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public class ZTagField<T> extends JTextPane {
        public ZTagField(List<T> sourceitems, StringBasedFactory<T> factory) {
            this(factory);
            setSourceItems(sourceitems);
        }
        public void setSourceItems(List<T> sourceitems) {
    		...
        }
        T[] arrItems = null;
        public T[] getItems() {
            if (rebuild) arrItems=...
            return arrItems;
        }
    2) La classe appelante
    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
    public class clTagChooser {
        ZTagField<clTag> txtTags = null;
        public clTagChooser(clArchive archive) {
            super();
            ...
        }
        protected void initBaseComponents() {
            // Le textpane, qu'on customise après
            txtTags = new ZTagField<clTag>(tagfactory);
        }
    	/** 
         * Retourne les items sélectionnés
         * @return clTag[]
         */
        public clTag[] getSelectedTags() {
            return txtTags.getItems(); // ?? retourne [Object cannot be cast to [clTag ????
            /** @todo Revoir cette horreur, mais c'est quoi encore que ce problème de cast ??? */
            //return Arrays.asList(txtTags.getItems()).toArray(new clTag[0]);
        }
    Contrairement à ce que j'avais dit, ça plante au runtime sur le return txtTas.getItems() avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    java.lang.ClassCastException: [Ljava.lan.Object; cannot be cast to [Lcom.zploger.Compute.clTag;

  5. #5
    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
    Apparemment, arrItems est un Object[], il ne peut pas être casté en clTag[].

    Comment initialises-tu ce tableau ? De quelle façon serait-il censé savoir qu'il doit être de type clTag ?

    (Et pourquoi ça ne s'appelle pas simplement items et Tag, boudiou ? D'ailleurs les noms de classes et interfaces sont censés commencer par une majuscule.)
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  6. #6
    lvr
    lvr est déconnecté
    Membre extrêmement actif Avatar de lvr
    Profil pro
    Responsable de projet fonctionnel
    Inscrit en
    Avril 2006
    Messages
    909
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Responsable de projet fonctionnel
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Avril 2006
    Messages : 909
    Points : 1 360
    Points
    1 360
    Par défaut
    Citation Envoyé par thelvin Voir le message
    Apparemment, arrItems est un Object[], il ne peut pas être casté en clTag[].
    Comment initialises-tu ce tableau ? De quelle façon serait-il censé savoir qu'il doit être de type clTag ?
    Parce que le tableau est de type T et que T est défini lors de l'instanciation de la classe en "new ZTagField<clTag>(...)"... sauf si je ne comprends toujours rien aux Generics...

    Citation Envoyé par thelvin Voir le message
    (Et pourquoi ça ne s'appelle pas simplement items et Tag, boudiou ? D'ailleurs les noms de classes et interfaces sont censés commencer par une majuscule.)
    Convention personnelle...

  7. #7
    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
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
            if (rebuild) arrItems=...
    c'est à cet endroit que ce trouve le problème, et c'est ce bout de code là qu'on aimerais voir


    Si t'as mis un truc du genre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    arrItems=new T[taille];
    Alors il est normal que tu te retrouve avec un Object. Les generics donnent des conventions sur les signature des méthode et la cohérence de celles-ci entre elles. Ils ne recompilent pas le code au vol. Donc ta méthode (qui retourne "T[]") en interne doit fonctionner exactement de la même manière qu'on travaille avec T étant Objecy ou T étant TrucBidule. Le code new T[] se traduit donc en byte code par new Object[] (Object étant l'ancètre commun).

    Enfin là je sur simplifie car, de mémoire, le compilateur va refuser new T[] en te disant que T n'est pas connu au moment de la compilation

  8. #8
    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
    Citation Envoyé par lvr Voir le message
    Parce que le tableau est de type T et que T est défini lors de l'instanciation de la classe en "new ZTagField<clTag>(...)"... sauf si je ne comprends toujours rien aux Generics...
    On va dire que c'est une compréhension naissante, mais il y a des lacunes, en effet.

    Pour compléter ce que dit tchize_, les Generics sont un outil d'aide au typage fort pendant la compilation. Au runtime les Generics n'existent plus, et le type T ne veut rien dire : il sera en fait du type avec lequel le tableau a été initialisé.
    Raison pour laquelle je demandais comment c'est fait.

    J'ai dit que mêler Generics et tableaux, c'est la plaie, et je plaisantais pas. Les tableaux ont une sémantique diamétralement opposée au concept des Generics.

    Note qu'en lisant ton code, je ne comprends pas pourquoi tu as besoin de définir un type générique T et pourquoi tu ne fais pas simplement du clTag à la place ?

    Convention personnelle...
    En Java il y a des conventions de codage généralement admises et cela va à leur encontre, mais c'est vrai que si tu ne montres ton code à personne c'est ton problème. *Hem*.
    Par contre, ne pas commencer tes noms de classe par une majuscule, ça peut te poser plus de soucis que tu ne l'imagines. Il y a pas mal de thirparties et de conventions qui comptent dessus.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  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
    Je rajouterai , qu'il y a de fortes chance pour que tu aie a partager un jour le code que tu fais avec quelqu'un.
    Ça ne coute pas très cher de prendre des habitudes de codage qui rendront le code plus lisible pour tous.

  10. #10
    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 Uther Voir le message
    Je rajouterai , qu'il y a de fortes chance pour que tu aie a partager un jour le code que tu fais avec quelqu'un.
    Avec le forum, le temps de te débloquer, par exemple

  11. #11
    lvr
    lvr est déconnecté
    Membre extrêmement actif Avatar de lvr
    Profil pro
    Responsable de projet fonctionnel
    Inscrit en
    Avril 2006
    Messages
    909
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Responsable de projet fonctionnel
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Avril 2006
    Messages : 909
    Points : 1 360
    Points
    1 360
    Par défaut
    Citation Envoyé par thelvin Voir le message
    Pour compléter ce que dit tchize_, les Generics sont un outil d'aide au typage fort pendant la compilation. Au runtime les Generics n'existent plus, et le type T ne veut rien dire : il sera en fait du type avec lequel le tableau a été initialisé.
    Raison pour laquelle je demandais comment c'est fait.
    C'est ça que je ne comprends pas, "il sera en fait du type avec lequel le tableau est initialisé", car ici il est clairement initialisé avec du clTag[]...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    public class ZTagField<T> extends JTextPane {
      protected List currentItems=new LinkedList(); 
      ...
      T[] arrItems=null;
      public T[] getItems() {
          if (rebuild) {
               // retravailler currItems, s'assurer que les non-T sont virés ou transformés en T, via le factory
               arrItems=(T[]) currentItems.toArray();
               rebuild=false;
          }
          return arrItems;
      }
    ...
    }
    ... sauf si le cast (T[]) compte pour du beurre et qu'il est initialisé avec du Object[] (ce que retourne le toArray()).
    Avant que vous n'hurliez, ma currentItems n'est pas une List<T> mais une List(*). Peut-être devrais-je mettre List<?> ?

    Citation Envoyé par thelvin Voir le message
    Note qu'en lisant ton code, je ne comprends pas pourquoi tu as besoin de définir un type générique T et pourquoi tu ne fais pas simplement du clTag à la place ?
    C'est un composant Swing générique. C'est pas tendance ?


    Citation Envoyé par thelvin Voir le message
    En Java il y a des conventions de codage généralement admises et cela va à leur encontre, mais c'est vrai que si tu ne montres ton code à personne c'est ton problème. *Hem*.
    Par contre, ne pas commencer tes noms de classe par une majuscule, ça peut te poser plus de soucis que tu ne l'imagines. Il y a pas mal de thirparties et de conventions qui comptent dessus.
    La programmation j'en fait depuis un paquet d'années (depuis mon commodore 64 à 10 ans, avec les POKE et les ??? pour ceux qui se souviennent), mais ça n'a été mon boulot que pendant 3 ans et je n'ai jamais eu de formation. Donc les conventions, c'est pas que je veux pas, c'est que je ne connais pas. S'il y a un lien qui décrit tout ça, c'est avec plaisir.
    J'ai déjà dû abandonner mon identation dès que j'ai quitté Vi et que mon jBuilder m'obligeait à identer autrement
    Ma convetion, c'est "clXXX" pour les classes principales, "itYYYY" pour les interfaces, "enZZZZ" pour les énumérations, ...
    Trève de bavardage, c'est quoi la solution alors ?
    Citation Envoyé par thelvin Voir le message
    J'ai dit que mêler Generics et tableaux, c'est la plaie, et je plaisantais pas. Les tableaux ont une sémantique diamétralement opposée au concept des Generics.
    Virer les arrays et ne travailler qu'en List ?

    Laurent

    (*) Parce que dans mon système, l'utilisateur saisit des textes. Pour chaque texte, sur base d'une liste de T connus, je déduis un T et je le mets dans la currentItems. Si je ne parviens pas en à identifier un, et suivant la config du composant, soit j'invalide la saisie, soit je crée un T sur base du factory et je l'ajoute dans la currentIetms, soit j'accepte le texte tel quel et je l'ajoute dans la currentIetms sous sa forme de String et c'est au moment du getItems, suivant encore la config du composant, je vire ces éléments inconnus ou j'en crée de nouveau composant. Cela permet à l'utilisateur d'introduire de nouvelles valeurs et d'éventuellement revenir en arrière avant que leur création ne soit effective. Peut-être mon approche n'est ici pas optimale.

Discussions similaires

  1. Réponses: 7
    Dernier message: 29/11/2007, 00h50
  2. Structure: Retour de méthode
    Par abcdefghijk dans le forum C++
    Réponses: 11
    Dernier message: 06/09/2007, 15h27
  3. Réponses: 8
    Dernier message: 19/07/2007, 16h40
  4. [Objet] Conseil retour de méthode
    Par charlene44 dans le forum Delphi
    Réponses: 10
    Dernier message: 06/03/2007, 09h57
  5. reflexion et type de retour des méthodes
    Par money mark dans le forum Langage
    Réponses: 2
    Dernier message: 09/04/2006, 18h46

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