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

Java Discussion :

Génériques. Connaitre le type supporté


Sujet :

Java

  1. #1
    Invité
    Invité(e)
    Par défaut Génériques. Connaitre le type supporté
    Bonjour,

    Je me suis crée un objet générique :
    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 Group<T> implements Comparable<Group<T>>, Serializable {
     
    	/** Serial version UID */
    	private static final long serialVersionUID = 741587360128392267L;
     
    	T holded;		
     
    	private String name;
    	private String description;
    	private List<T> items;	
     
            // Constructeurs et accesseurs ...
    }
    Mais je voudrais pouvoir donner à mon attribut 'holded' la classe de l'objet supporte (le type de T). Je voudrais faire cela sans avoir à le recevoir dans le constructeur.
    Est-ce possible ?

    Merci

  2. #2
    Modérateur
    Avatar de dinobogan
    Homme Profil pro
    ingénieur
    Inscrit en
    Juin 2007
    Messages
    4 073
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations professionnelles :
    Activité : ingénieur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 4 073
    Par défaut
    Je n'ai pas très bien compris ta question.
    Tu veux restreindre le type T ?
    Tu peux obliger le type T à dériver d'une classe, lors de la déclaration.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java
    Que la force de la puissance soit avec le courage de ta sagesse.

  3. #3
    Expert confirmé
    Avatar de djo.mos
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    4 666
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 4 666
    Par défaut
    Bonjour,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    Class<T> type = (Class<T>) ((ParameterizedType) getClass()
    				.getGenericSuperclass()).getActualTypeArguments()[0];
    @+

  4. #4
    Invité
    Invité(e)
    Par défaut
    Super grand merci djo.mos.

    Sauf que j'ai une ClassCastException .. :'(
    java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
    Dernière modification par Invité ; 20/02/2008 à 16h36.

  5. #5
    Modérateur
    Avatar de dinobogan
    Homme Profil pro
    ingénieur
    Inscrit en
    Juin 2007
    Messages
    4 073
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations professionnelles :
    Activité : ingénieur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 4 073
    Par défaut
    Surement un problème de parenthèses. Tu as essayé
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    (ParameterizedType)( getClass().getGenericSuperclass() )
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java
    Que la force de la puissance soit avec le courage de ta sagesse.

  6. #6
    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,


    Le ClassCastException est normal... puisque rien ne garantit que le retour soit un ParameterizedType...


    Que veux-tu faire exactement ? Obtenir le type paramétré ? ce n'est pas possible !


    Un peu de lecture : Les Generics ne sont pas des Templates comme les autres !


    a++

  7. #7
    Invité
    Invité(e)
    Par défaut
    Oui, j'en étais arrivé à la même conclusion pour la ClassCastException..

    Ca m'embête bien de devoir passer également la classe au constructeur, ça fais "moins pro" et double un peu le fonctionnement puisque je dois préciser le type dans les < .. > et au constructeur.
    Donc un petit bémol aux génériques.


    Edit : Note qui si je voulais je pourrais tenter un truc du style :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
      public void addItem(T item) {
         if ( holded==null ) {
            holded = (Class<T>) item.getClass();
         }
         items.add(item);
      }
    Mais ça ne m'arrange pas car tant que je n'ai pas ajouté d'item je ne sais pas ce qu'il contient..

    Ps : Merci pour ton article. Je ne l'avais pas lu parce que pas trouvé..
    Dernière modification par Invité ; 21/02/2008 à 12h49.

  8. #8
    Modérateur
    Avatar de dinobogan
    Homme Profil pro
    ingénieur
    Inscrit en
    Juin 2007
    Messages
    4 073
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations professionnelles :
    Activité : ingénieur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 4 073
    Par défaut
    Peur-être devrais-tu revoir la façon de penser ta conception ?
    Dans ton exemple (je ne sais pas si ta question initiale portait dessus ou si c'est un exemple rapide pour nous faire comprendre ta problématique) la méthode "addItem" n'a aucune raison conceptuelle d'ajouter un élément si le paramètre est null.
    Pour quelle raison veux-tu instancier "dynamiquement" cet objet ?
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java
    Que la force de la puissance soit avec le courage de ta sagesse.

  9. #9
    Invité
    Invité(e)
    Par défaut
    Non, c'est un véritable objet que je serais amené à utiliser.

    EN effet, 'addItem()' ne dois pas ajouter un objet null mais je ne vois pas en quoi cela change mon problème.
    Je ne connaitrais toujours pas le type d'objet supporté avant d'en avoir ajouté un (non null)

  10. #10
    Membre Expert
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    1 252
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2004
    Messages : 1 252
    Par défaut
    C'est dangereux d'utiliser cela comme ça :

    Mettons que tu aies B extends C.

    Tu t'attends à avoir une classe B ou C car ce sont celles que tu as définies. Mais une fois que tu as choisi C, tu ne pourras plus accepter de B, car leurs classes sont différentes.

  11. #11
    Expert confirmé
    Avatar de djo.mos
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    4 666
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 4 666
    Par défaut
    @Blaise: , j'y comprends plus rien moi non plus: le bout de code que je t'ai donné marche parfaitement dans un contexte web (je l'utilise dans mes DAOs JPA) mais donne la ClassCastException quand je le testes dans un contexte java ordinaire

    Je vais approfondir ça dès que je respires un peu au boulot

  12. #12
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par dingoth Voir le message
    Tu t'attends à avoir une classe B ou C car ce sont celles que tu as définies. Mais une fois que tu as choisi C, tu ne pourras plus accepter de B, car leurs classes sont différentes.
    Oui bien sur mais je ne vois pas ou est le problème. Si ma classe Group peux contenir des objets Parent et que je décide de l'istancier pour qu'elle ne contienne que des Enfant (qui étendent Parent). Il est normal que je ne puisse plus rajouter de Parent..
    Enfin, je trouve..
    Edit : Ha non, désolé je n'avais pas compris. Oui en effet c'est dangereux. Mais pas dans le sens de l'ajout. Disons que je fasse ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Group grp = new Group<Parent>();
     
    Enfant e = new Enfant("Plip");    // extends Parent
    grp.addItem(e);
     
    Parent p = new Parent("Plop");
    grp.addItem(p);
    Je m'attends à avoir holded (classe gérée par mon groupe) qui vaut 'Parent' mais étant donné que mon premier ajout est 'Enfant'. Je suis foutu.
    Par contre je pourrais toujours ajouter un objet 'Parent'




    Citation Envoyé par djo.mos Voir le message
    @Blaise: , j'y comprends plus rien moi non plus: le bout de code que je t'ai donné marche parfaitement dans un contexte web (je l'utilise dans mes DAOs JPA) mais donne la ClassCastException quand je le testes dans un contexte java ordinaire

    Je vais approfondir ça dès que je respires un peu au boulot
    Dans mon cas ce seras dans un projet web mais je développe et test mon DAO hors du contexte web avant.
    Ce n'est pas du tout bloquant pour mon projet mais je cherche aussi une réponse au problème...
    Remarque qu'après avoir lu l'article de d'adiGuba il semble logique que cela ne sois pas possible. En cherchant sur Internet, je n'ai pas trouvé de réponse directe mais une foule d'article sur les Generics, peut-être y trouverais-je une réponse. (Même si je ne trouve pas de réponse j'aurais au moins appris un tas de choses sur le sujet)

  13. #13
    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 djo.mos Voir le message
    @Blaise: , j'y comprends plus rien moi non plus: le bout de code que je t'ai donné marche parfaitement dans un contexte web (je l'utilise dans mes DAOs JPA) mais donne la ClassCastException quand je le testes dans un contexte java ordinaire
    Cela ne vient pas d'une différence de contexte mais d'une différence d'héritage.


    Ici on obtient une exception car la super-class n'est pas Generics, donc getGenericSuperclass() ne retourne pas un ParameterizedType mais une simple Class...


    Mais même lorsque la superclass est Generics on ne peut pas forcément obtenir cette information...

    Prenons la classe generics suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    class MaClasseGenerics<T> {
     
    }
    Lorsqu'on hérite de cette classe on a deux choix :
    1. Conserver les Generics, ou les spécialiser, par exemple :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      class MaClasseFilleGeneric<T> extends MaClasseGenerics<T> {
       
      }
       
      class MaClasseFilleGeneric2<T extends Number> extends MaClasseGenerics<T> {
       
      }
      Dans ce cas le code donné plsu haut retournera bien un ParameterizedType, mais le getActualTypeArguments() ne retournera pas une Class mais un objet Type représentant le type paramétré... qui ne te donnera principalement que le nom du type paramétré (T) et son bound-type (Object comme rien n'est précisé)

    2. A l'inverse si tu fais ceci :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      class MaClasseStandard extends MaClasseGenerics<Double> {
       
      }
      Alors le code donné plus haut fonctionnera parfaitement, et te renverra bien le Double, mais seulement parce qu'il s'agit d'un héritage qui spécifie "en dur" le type paramétré...




    Il faut bien se rappeler que la reflection retourne des informations globales à un type, et non pas propre à une instance. Donc grosso modo tout ce qui est retourné par la reflection doit se retrouver dans le code de la classe en question (et non pas dans le code où elle est utilisée).




    Pour moi la meilleur solution serait de passer le type paramétré en paramètre du constructeur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    class MaClasseGeneric<T> {
    	private final Class<T> type;
     
    	public MaClasseGeneric(Class<T> type) {
    		if (type==null) {
    			throw new NullPointerException();
    		}
    		this.type = type;
    	}
    }

    a++

  14. #14
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par adiGuba Voir le message
    Pour moi la meilleur solution serait de passer le type paramétré en paramètre du constructeur :
    Oui il me semblait bien que c'était la seule solution. C'est surement pour cela que l'on retrouve cette pratique un peux partout. Mais j'aurais juste aimé pouvoir faire sans.. Tant pis .

    Merci.

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

Discussions similaires

  1. [FTP] Connaitre le type mime d'un fichier
    Par jak0 dans le forum Langage
    Réponses: 15
    Dernier message: 18/07/2006, 11h32
  2. [CSS][formulaire] connaitre le type d'un champ input
    Par psychomatt dans le forum Mise en page CSS
    Réponses: 3
    Dernier message: 22/09/2005, 12h13
  3. Connaitre le type de character set
    Par vbcasimir dans le forum Administration système
    Réponses: 4
    Dernier message: 02/08/2005, 13h02
  4. Réponses: 10
    Dernier message: 27/04/2005, 11h26
  5. Connaitre le type de chaque col d'une table Paradox
    Par mjp dans le forum Bases de données
    Réponses: 2
    Dernier message: 03/02/2005, 21h00

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