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 :

Généricité et .class


Sujet :

Langage Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Étudiant
    Inscrit en
    Novembre 2005
    Messages
    97
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2005
    Messages : 97
    Par défaut Généricité et .class
    Bonjour,

    Je bosse actuellement sur un projet J2EE et je voudrais écrire une classe générique pour les DAO.

    Voici le code que je pensais pouvoir écrire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    public abstract class Dao<T> {
     
    public void getObjetById (Session s , Integer id)
    {
     T result = s.get(T.class,id);	
    }	
    }
    Je ne comprends pas pourquoi ce code ne compile pas.

    Auriez vous une solution à mon problème?

    Merci

  2. #2
    Membre chevronné Avatar de djsnipe
    Inscrit en
    Mai 2008
    Messages
    440
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 440
    Par défaut
    Les types génériques sont perdus lors de l'exécution, il n'est donc pas possible d'obtenir les infos de type T.class ou new T(). Ecrire un DAO avec les génériques java de cette manière ne me semble pas possible, même si je trouve ça dommage dans ce cas, ou la cast va perdurer.

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


    Comme le type paramétré est perdu à l'exécution, la solution est de le stocker manuellement, par 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
    public abstract class Dao<T> {
     
    	private final Class<T> type;
     
    	public Dao(Class<T> type) {
    		this.type = type;
    		if (this.type==null) {
    			throw new IllegalArgumentException("null type");
    		}
    	}
     
    	public void getObjetById (Session s , Integer id) {
    		T result = s.get(this.type, id);	
    	}	
    }

    A lire sur le blog sur ce sujet : Les Generics ne sont pas des Templates comme les autres !

    a++

    [edit] grillé

  4. #4
    Membre éprouvé
    Avatar de Mik ArBer
    Homme Profil pro
    Architecte logiciel
    Inscrit en
    Avril 2007
    Messages
    36
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Architecte logiciel
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2007
    Messages : 36
    Par défaut
    T n'existe pas au "run-time", donc le compilateur anticipe les problèmes et n'accepte pas tu cherches à récupérer son type.

    Je ne sais pas si cela convient à ton besoin, mais une des solutions les plus simples et de passer en paramètres le type de classe. J'ai aussi interprété que ta méthode getObjectById ramène une instance de type T.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    public abstract class Dao<T> {
     
    	public  T getObjetById(Session s, Integer id, Class<T> type) {
     
    		T result = s.get(type , id);
     
    		return result;
    	}
    }
    A+

    Mik

  5. #5
    Membre chevronné Avatar de djsnipe
    Inscrit en
    Mai 2008
    Messages
    440
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 440
    Par défaut
    L'ennui de cette approche c'est de devoir passer le type à chaque appel du DAO. Même si ça marche, je préfère garder des cast avec un DAO non generic-ready

    adiGuba, dans exemple que tu donnes, il ne serait pas possible selon moi de profiter du type paramétré comme valeur de retour de la méthode getObjectById. C'est bien ça ?

  6. #6
    Membre Expert
    Avatar de gifffftane
    Profil pro
    Inscrit en
    Février 2007
    Messages
    2 354
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire (Rhône Alpes)

    Informations forums :
    Inscription : Février 2007
    Messages : 2 354
    Par défaut
    Dans l'ensemble, lorsque l'objet vient de nulle part, comme c'est souvent le cas avec les DAO, je pense que l'ancienne forme, par les casts, est la meilleure.

    Les génériques exigent une logique complète dans la définition des types, et n'admettent pas qu'un objet x, y ou z devienne un T, S ou P sans warning ; et, s'il faut protéger le warning, autant utiliser les casts classiques directement, il me semble.

    Voici toutefois un exemple - inapplicable dans le contexte d'une DAO - où le code ne stipule ni type générique ni cast dans l'activation, seulement dans sa déclaration :
    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
     
    // une méthode quelque part...
    public static void main(String[] args) 
    {
      DAO<Date> daodate;
     
      // Plus besoin de répéter le type générique Date !
      daodate = DAO.nouv();
    }
     
    // le type générique, parfaitement classique
    // --------------------
    public class DAO<T>
      {
        private T objt;
     
        public T getObj(int id)
        {
          return objt;
        }
     
        public void setObj(T obj)
        {
          objt = obj;
        }
     
        // L'ASTUCE : une méthode statique de création générique
        public static <P> DAO<P> nouv()
        {
          return new DAO<P>();
        }    
      }
    J'utilise ici la notion d'inférence (What is type argument inference?). C'est une notion pratique, mais elle ne dispense pas d'avoir à préciser le type générique dans le code, et elle ne permet pas de le découvrir à l'exécution.

Discussions similaires

  1. Classe pour la création d'un graphe xy
    Par Bob dans le forum MFC
    Réponses: 24
    Dernier message: 03/12/2009, 17h20
  2. Généricité et création de classes dynamiques
    Par virulent dans le forum Langage
    Réponses: 4
    Dernier message: 11/09/2009, 09h28
  3. Classe intervalle C++ avec généricité
    Par sanskrit76 dans le forum Débuter
    Réponses: 3
    Dernier message: 24/04/2009, 14h08
  4. Généricité en Java (classe avec paramètre)
    Par epcilone059 dans le forum Langage
    Réponses: 1
    Dernier message: 27/03/2009, 12h05
  5. Réponses: 31
    Dernier message: 30/03/2006, 16h57

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