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 :

L'utilité de la généricité de Java


Sujet :

Java

  1. #1
    Membre éclairé Avatar de spring.time
    Femme Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2011
    Messages
    294
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 35

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2011
    Messages : 294
    Par défaut L'utilité de la généricité de Java
    Bonjour,
    j'utilise le pattern Dao, pour implémenter la couche d'accès aux données, j'ai donc créé une interface générique comme ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    public interface GenericDAO<T, PK extends Serializable> {
     
    	 /** Persist the newInstance object into database */
        void create(T newInstance);
     
    ...
    }
    une implémentation de cette interface en utilisant le framework Hibernate:
    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
     
    public  class GenericDAOImpl<T, Pk extends Serializable> implements GenericDAO<T, Pk >{
     
    	private Class<T> type;
    	private Session session;
     
     
    	public GenericDAOImpl(Class<T> classe) {
    		this.type = classe;
    	}
     
     
    	@Override
    	public void create(T newInstance) {
    		try{
    			this.session = HibernateUtil.getSession();
    			this.session.beginTransaction();
    			this.session.save(newInstance);
    			this.session.getTransaction().commit();
    			System.out.print("oui");
    		}
    		catch (HibernateException e){
    			System.out.print(e.getMessage());
    		}
    	}
     
    ...}
    mais je ne comprends pas la différence entre Class<T> et T ? parce que j'ai fait ceci,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    public T read(Pk id) {
    		try {
    			this.session = HibernateUtil.getSession();
    			this.session.beginTransaction();
    			this.type = (Class<T>)this.session.get(this.type, id);
     
     
    		} catch (HibernateException e) {
    			System.out.print(e.getMessage());
    		}
    		return (T) this.type;		
    	}
    mais malheureusement, le read ne marche pas:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    GenericDAO<Projet,Integer> genericDAO = new GenericDAOImpl<Projet, Integer>(null);
    Projet projet2 = new Projet();
    	projet2 = genericDAO.read(2);
    	System.out.print(projet2.getNom());
    je ne comprends ce 'null'.

    pourquoi c'est permis de faire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    private  Class<Projet> projet;
    private  ProjetDAO projetDAO =  new ProjetDAOImp(projet );
    Projet p = new Projet();
    p.setNom("projet1");
    projetDAO.create(p);
    et merci d'avance.

  2. #2
    Modérateur
    Avatar de Gugelhupf
    Homme Profil pro
    Analyste Programmeur
    Inscrit en
    Décembre 2011
    Messages
    1 326
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Analyste Programmeur

    Informations forums :
    Inscription : Décembre 2011
    Messages : 1 326
    Billets dans le blog
    12
    Par défaut
    Bonsoir,


    mais je ne comprends pas la différence entre Class<T> et T ?
    Class est une classe générique du standard Java. On s'en sert lorsqu'on fait de l'instrospection (ou "reflexivité").
    T est ton type générique.

    mais malheureusement, le read ne marche pas:
    Ce n'est pas très précis comme erreur
    Tu récupères un Class<T>, et tu veux le caster en T ? C'est comme si tu essayais de caster un String en Integer...

    En fait je pense que tu t'y prends un peu mal à cette ligne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    this.type = (Class<T>)this.session.get(this.type, id);
    Ça devrait plus ressembler à :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    T valReturn = this.session.get(this.type, id);
    Enfin je pense...
    N'hésitez pas à consulter la FAQ Java, lire les cours et tutoriels Java, et à poser vos questions sur les forums d'entraide Java

    Ma page Developpez | Mon profil Linkedin | Vous souhaitez me contacter ? Contacter Gokan EKINCI

  3. #3
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Billets dans le blog
    2
    Par défaut
    Salut,

    T représente un type (une classe) quelconque dans ton cas, et Class<T> représente une instance de Class d'un object de type T.

    Quand tu écris :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public  class GenericDAOImpl<T, Pk extends Serializable> implements GenericDAO<T, Pk >{
     
    	private Class<T> type;
    	private Session session;
     
     
    	public GenericDAOImpl(Class<T> classe) {
    		this.type = classe;
    	}
     
           ...
    tu crées une classe, appelée GenericDAOImpl, qui est paramétrée par 2 types, T et Pk. T est de type quelconque, et Pk est un type qui implémente Serializable.

    Le constructeur de cette classe a un paramètre, dont le type est la classe T. Si tu crées une instance de cette classe, tu devras indiquer pour quel type, et tu devras passer la classe correspondante en argument du constructeur.

    Par exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    new GenericDAOImpl<Integer, String>(Integer.class);
    Ou
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    new GenericDAOImpl<ArrayList, Integer>(ArrayList.class);

    Il ne faut pas passer null en paramètre, si tu te sers de la variable type de GenericDAO, pour éviter une NullPointerException. Si tu ne t'en sers pas, autant la supprimer (ce qui n'est pas le cas apparemment).

    En tout cas, tu ne peux pas écrire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public T read(Pk id) {
    		try {
    			this.session = HibernateUtil.getSession();
    			this.session.beginTransaction();
    			this.type = (Class<T>)this.session.get(this.type, id);
     
     
    		} catch (HibernateException e) {
    			System.out.print(e.getMessage());
    		}
    		return (T) this.type;		
    	}
    Si type est du type Class<T>, tu ne pourras pas le caster en T. Je n'y connais rien en hibernate mais, à mon avis, le code devrait être :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public T read(Pk id) {
              T value = null;
    		try {
    			this.session = HibernateUtil.getSession();
    			this.session.beginTransaction();
    			value = this.session.get(this.type, id);
     
     
    		} catch (HibernateException e) {
    			System.out.print(e.getMessage());
    		}
    		return value;	
    	}
    La méthode T get(Class<T>, Pk) de session doit permettre de lire un bean de classe T, et pour pouvoir instancier ce bean, on lui fournit un object, qui est un objet de classe Class<T>, et qui représente la classe de ce bean.
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  4. #4
    Membre éclairé Avatar de spring.time
    Femme Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2011
    Messages
    294
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 35

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2011
    Messages : 294
    Par défaut
    Salut
    je vous remercie beaucoup pour vos explications, ça devient plus clair
    Donc;
    T est n'importe quel type de classe.
    class<T> est une instante d'une classe de type T.

    oui j'ai pu régler le problème de read grace à vous:
    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 T read(Pk id) {
    		T value= null;
    		try {
    			this.session = HibernateUtil.getSession();
    			this.session.beginTransaction();
    			value = (T) this.session.get(this.type, id);
     
     
    		} catch (HibernateException e) {
    			System.out.print(e.getMessage());
    		}
    		return value;	
    	}
    et le test:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    GenericDAO genericDAO = new GenericDAOImpl<Projet ,Integer >(Projet.class);
    	Projet projet = new Projet();
    	projet = (Projet) genericDAO.read(2);
    	System.out.print(projet.getNom());
    maintenant j'ai une classe ProjetDAOImp étendant de la précedente classe
    GenericDAOImpl comme ceci;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    public  class ProjetDAOImp extends GenericDAOImpl<Projet, Integer> implements ProjetDAO {
    son constructeur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    public ProjetDAOImp(Class<Projet> classe) {
    		super(classe);
    		// TODO Auto-generated constructor stub
    	}
    si je fais comme cela pour instancier ProjetDAOImp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    ProjetDAO projetDAO = new ProjetDAOImp(Projet.class);
    projet = projetDAO.read(2);
    	System.out.print(projet.getNom());
    cela revient au même, c'est correct ?

  5. #5
    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
    Citation Envoyé par spring.time Voir le message
    class<T> est une instante d'une classe de type T.
    non, une instance d'une classe de type java.lang.Class

  6. #6
    Membre éclairé Avatar de spring.time
    Femme Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2011
    Messages
    294
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 35

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2011
    Messages : 294
    Par défaut
    une question "Gugelhupf", s'il vous plait
    "
    Class est une classe générique du standard Java. On s'en sert lorsqu'on fait de l'instrospection (ou "reflexivité").

    "
    je n'ai pas bien compris, que voulez vous dire par ces 2 mots:
    l'instrospection, reflexivité

    Merci

  7. #7
    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
    Grosso modo, quand on veux explorer ce qu'est une instance précise, mais qu'on en a pas la moindre idée lors de la compilation. Il existe une série de choses, comme java.lang.Class qui permettent de faire cette exploration, déterminer les méthodes disponibles, les propriétés, la hierarchie des parents, etc.

  8. #8
    Membre éclairé Avatar de spring.time
    Femme Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2011
    Messages
    294
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 35

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2011
    Messages : 294
    Par défaut
    je n'ai jamais pensé à cela :
    "
    Grosso modo, quand on veux explorer ce qu'est une instance précise, mais qu'on en a pas la moindre idée lors de la compilation
    "

    ça peut arriver ?

  9. #9
    Membre éclairé Avatar de spring.time
    Femme Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2011
    Messages
    294
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 35

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2011
    Messages : 294
    Par défaut
    une 2ème question si vous le permettez ,
    j'ai lu que les classes generiques comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
     
    public  class ArrayList<T> {
     
        public T get() { ... }
     
        public  void add(T t) { ... }
     
    }
    nous évite de faire le cast à chaque lecture.

    pourquoi dans mon exemple, je dois caster ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
     
    GenericDAO genericDAO = new GenericDAOImpl<Projet ,Integer >(Projet.class);
    	Projet projet = new Projet();
    	projet = (Projet) genericDAO.read(2);
    	System.out.print(projet.getNom());
    Merci

  10. #10
    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 spring.time Voir le message
    je n'ai jamais pensé à cela :
    "Grosso modo, quand on veux explorer ce qu'est une instance précise, mais qu'on en a pas la moindre idée lors de la compilation"
    ça peut arriver ?
    En fait l'introspection ne se limite pas à ça, mais oui, ça peut arriver.

    Par exemple quand tu veux configurer une application à la mode Spring avec des fichiers XML qui disent quelles classes au lieu de quelles autres utiliser pour quels service.
    Par exemple pour configurer mon programme de soirée, j'ai une classe Table, et il lui faut une instance de type Plat, et là moi je veux configurer l'appli pour utiliser la classe Choucroute, qui implémente Plat.
    Dans ma conf' Spring je suis pas dans un IDE Java, c'est juste un fichier XML, je peux pas faire vraiment référence à des classes, je mets juste le nom des classes.
    Et donc je dis d'utiliser ma classe Table et ma classe Choucroute, mais comment Spring peut-il deviner qu'il doit donner l'un à l'autre ? Parce qu'il a regardé les classes, constaté que Table a besoin d'un Plat et offre une méthode setPlat(Plat) pour le recevoir, et que Choucroute implémente Plat et répond donc au besoin.
    Sans introspection, Spring ne peut pas faire ça et donc pas exister (bon, c'est pas vrai, mais il serait nettement moins simple à faire et utiliser.)

    Citation Envoyé par spring.time Voir le message
    pourquoi dans mon exemple, je dois caster ?
    T'es pas obligé de caster, mais t'as le droit si t'as envie de le faire quand même. Le compilateur te trouve bizarre mais il dit rien, chacun ses coutumes.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  11. #11
    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
    Citation Envoyé par spring.time Voir le message

    ça peut arriver ?
    Oui, ça peux arriver, même si ce n'est pas souvent le cas. Je vais donner quelques exemple en plus de celui de Spring qui a été donné.

    Hibernate: clairement, quand hibernate a été compilé, il n'avait pas la moindre connaissance de ta classe Projet. Pourtant, à partir de ses fichier de config, il est capable de créer un classe Projet, de l'initialiser avec les données de la base de données et de te la retourner. Pour ça il a besoin de l'introspection. D'aller chercher le java.lang.Class<Project> associé à ta classe Projet, d'explorer les types de ses champs, de trouver les getters / setters, de trouver les constructeurs

    La sérialisation: sauver des instances dans un fichier. L'api de Serialisation n'avait pas non plus connaissance de tes classes à leur compilation, et pourtant elles peuvent sérialiser / deserializer n'importe quoi implementant Serializable. La aussi l'introspection entre en jeu.

    En général, ce sont des apis générales (hibernate, spring, xstream, jsf, jpa, ejb, ...) qui font de l'introspection, c'est rarement utilisé directement dans un code d'un projet, même si ça peux arriver.

Discussions similaires

  1. Généricité développement Java
    Par debloc dans le forum Débuter avec Java
    Réponses: 1
    Dernier message: 12/12/2012, 11h01
  2. Comment utiliser la généricité en java ?
    Par Adorien dans le forum Langage
    Réponses: 3
    Dernier message: 27/04/2010, 12h35
  3. Utilité de la persistance pour java web ?
    Par ChristopheD dans le forum Général Java
    Réponses: 4
    Dernier message: 05/01/2010, 18h08
  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. Généricité en java
    Par NewbiZ dans le forum Général Java
    Réponses: 6
    Dernier message: 11/02/2009, 12h27

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