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 :

Class<T> t : comment executer et un méthode d'un type générique et avoir la valeur de retour ?


Sujet :

Java

  1. #1
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2014
    Messages
    72
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Moselle (Lorraine)

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

    Informations forums :
    Inscription : Juin 2014
    Messages : 72
    Par défaut Class<T> t : comment executer et un méthode d'un type générique et avoir la valeur de retour ?
    Bonjour à tous

    j'ai cette classe :

    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 class MaClasse <T, M> {
     
    	@Autowired
    	private Class<T> membre1;
     
    	public Class<M> maMethodeQuiRenvoieUnResultat(Class<M> param1) {
               // Je veux pouvoir executer une methode qui est définie dans param1 (exemple cette méthode calcule et renvoie la date d'aujourd'hui+3 jours)
               // ça donnerait : Date d = param1.getDateDansTroisJours();
     
               // ENSUITE :
     
               // executer une méthode de membre1 qui prend une date en paramètre et renvoi un objet de type Class<M>
               // ça donnerait : Class<M> res = membre1.uneMethode(Date d);
            }
    }
    Quelle est la meilleur façon de pouvoir accéder et executer donc les méthodes définies donc "Class<T> membre1" et "Class<M> param1" ?

    En vous remerciant d'avance.

  2. #2
    Membre confirmé Avatar de Badshade23
    Homme Profil pro
    Développeur Java
    Inscrit en
    Décembre 2014
    Messages
    203
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Décembre 2014
    Messages : 203
    Par défaut
    Salut,

    Tu es obligé de mettre ton paramètre en class générique ? Tu ne peux pas utiliser une class mère ou encore une interface que tes classes implémenteraient ?

    La méthode appelée dedans est toujours la même ? Ou elle change selon l'objet passé en paramètre ?

  3. #3
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2014
    Messages
    72
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Moselle (Lorraine)

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

    Informations forums :
    Inscription : Juin 2014
    Messages : 72
    Par défaut
    Merci pour ta réponse Badshade23,

    Effectivement je pourrais mettre une classe mère ou interface (j'y pas pensé dans mon contexte actuel d'utilisation).
    dans mon contexte le paramètre "param1" serait un un Service Springboot donc techniquement je peux faire hériter mes services depuis une classe service mere mais je ne sais si cela est cohérent étant donné que les services ne sont pas liés entre eux.

    de la même manière pour le membre "membre1" qui serait un Repository.

    quant à la méthode appelée, que ce soit pour le service ou le repository, elle ne change pas. mais j'aimerais aussi savoir comment faire dans le cas où elle changerait.

    Merci

  4. #4
    Membre confirmé Avatar de Badshade23
    Homme Profil pro
    Développeur Java
    Inscrit en
    Décembre 2014
    Messages
    203
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Décembre 2014
    Messages : 203
    Par défaut
    Citation Envoyé par lenas_tshaleb Voir le message
    Effectivement je pourrais mettre une classe mère ou interface (j'y pas pensé dans mon contexte actuel d'utilisation).
    dans mon contexte le paramètre "param1" serait un un Service Springboot donc techniquement je peux faire hériter mes services depuis une classe service mere mais je ne sais si cela est cohérent étant donné que les services ne sont pas liés entre eux.
    Personnelement, je n'ai jamais eu besoin de donner un service instancier par spring en paramètre a une méthode. Mais dans ton cas si vraiment tu veux faire une méthode générique au lieu de faire une class mère pour tes services je ferai plutôt une interface qui contient la ou les méthode que tes service doivent avoir en commun.

    Citation Envoyé par lenas_tshaleb Voir le message
    mais j'aimerais aussi savoir comment faire dans le cas où elle changerai
    Si après tu veux faire une méthode qui est générique et qui exécute une méthode choisi au dernier moment de ton objet générique passé en paramètre (pas sur que se soit français tout ça ).
    Tu dois donner à ta méthode générique la méthode que celle*ci doit éxécuter (elle ne peut pas la deviner toute seule).

    Citation Envoyé par lenas_tshaleb Voir le message
    de la même manière pour le membre "membre1" qui serait un Repository.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    @Autowired
    	private Class<T> membre1;
    Je ne pense pas que tu puisses faire ça (à confirmer). Car tu demande à Spring de t'injecter un repository mais tu ne lui précise pas le quel ...
    Il ne pourra pas le deviner tout seul encore une fois.

  5. #5
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2014
    Messages
    72
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Moselle (Lorraine)

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

    Informations forums :
    Inscription : Juin 2014
    Messages : 72
    Par défaut
    Personnelement, je n'ai jamais eu besoin de donner un service instancier par spring en paramètre a une méthode. Mais dans ton cas si vraiment tu veux faire une méthode générique au lieu de faire une class mère pour tes services je ferai plutôt une interface qui contient la ou les méthode que tes service doivent avoir en commun.
    Je rectifie : param1 serait une Entity SpringBoot et non pas un service (au temps pour moi).

    Tu dois donner à ta méthode générique la méthode que celle*ci doit éxécuter (elle ne peut pas la deviner toute seule).
    Comment faire cela ? un exemple ?

    Je ne pense pas que tu puisses faire ça (à confirmer). Car tu demande à Spring de t'injecter un repository mais tu ne lui précise pas le quel ...
    Il ne pourra pas le deviner tout seul encore une fois.
    je doute aussi que cela marche car effectivement il essaye d'injecter quelque chose qu'il ne connait pas encore, je me demande si il y a une solution à ça en Java

  6. #6
    Membre confirmé Avatar de Badshade23
    Homme Profil pro
    Développeur Java
    Inscrit en
    Décembre 2014
    Messages
    203
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Décembre 2014
    Messages : 203
    Par défaut
    Citation Envoyé par lenas_tshaleb Voir le message
    Comment faire cela ? un exemple ?
    J'ai fait ça il y a longtemps il faudrait que je retrouve mon code ... Mais dans mes souvenirs je passais une instance d'un objet et un string (nom de la méthode) en paramètre de la méthode. Puis via une librairie tierce je faisais une sorte d’exécuter dessus. Actuellement je n'ai jamais eu besoin de réitérer ce style de code et niveau d’abstraction est pour moi rarissime et souvent peut-être effectuer autrement.

    Citation Envoyé par lenas_tshaleb Voir le message
    je doute aussi que cela marche car effectivement il essaye d'injecter quelque chose qu'il ne connait pas encore, je me demande si il y a une solution à ça en Java
    Pour moi c'est impossible. Quand tu lances ton conteneur Spring, il va scanner tous les répertoires que tu lui as indiqués (via @SpringBootApplication ou autre) et à chaque fois qu'il tombe sur une annotation, il regarde avant d'injecter l'objet si celui-ci existe déjà dans son contexte ou non. Si il ne le trouve pas, il l'instancie et le place dans son contexte (si c'est un singleton). Ici Spring ne peut pas l'instancier, il ne connaît pas la classe. Le niveau d'abstraction est beaucoup trop haut et pour moi ce n'est pas à Spring de gérer ça. Mais plutôt à toi, plus tard de set cet attribut. Apres peut être en utilisant le XML pour instancier le Bean et non l'annotation ... Mais encore une fois je ne pense pas que ce sois réalisable.

    Tu ne peux pas traiter le problème autrement ? Pourquoi tu en es arriver à cette réflexion ?

  7. #7
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2014
    Messages
    72
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Moselle (Lorraine)

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

    Informations forums :
    Inscription : Juin 2014
    Messages : 72
    Par défaut
    J'ai trouvé comment faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    try {
            Class<T> genericObj;
     
    	Method maMethode = genericObj.getClass().getDeclaredMethod("nomDeMaMethode", null); // null pour dire qu'elle n'a pas de paramètre
    	String result = (String) maMethode.invoke(genericObj, new Object[0]); //new Object[0] pour ne pas mettre null car il attend une liste de params
     
    } catch (NoSuchMethodException | SecurityException e) {
    	e.printStackTrace();
    }
    pour le @autowired, j'ai directement passé le repo en paramètre en y declarant une interface dont hérite le repo.

    Merci pour ton aide.

  8. #8
    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
    Hello,

    oui bien entendu, la réflexion permet toujours de faire ça mais... C'est débile !

    Tu as gagné quoi en faisant ça ? A quoi ça sert que le langage nous permette d'appeler directement les méthodes genre uneVariable.appelMethode(), si on préfère utiliser getDeclaredMethod()?

    Ce que je veux dire c'est que si tu es content de ce que tu as maintenant, bon, dommage mais ça te regarde. Par contre personne qui assiste à ça ne doit croire que c'était une manière utile de faire quoi que ce soit.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  9. #9
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2014
    Messages
    72
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Moselle (Lorraine)

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

    Informations forums :
    Inscription : Juin 2014
    Messages : 72
    Par défaut
    ton commentaire est nul et complètement inutile !!

    si tu ne peux pas donner un avis plus constructif, je t'invite à ne rien dire.

    si tu ne peux pas comprendre l'utilité de certaines choses alors reste polie au moins !!

  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
    Absolument pas.

    Je te l'ai dit, ce que tu fais, ça te regarde. Mais on ne peut pas abandonner un débutant qui tombe sur cette page et penserait que tout ça a un sens. Ça n'en a pas. C'est à ça que sert ce que je dis.

    De toute façon quand je pose la question "à quoi ça sert", si ça sert vraiment à quelque chose eh bien il suffirait de répondre à la question. Quand au lieu de répondre on dit "si tu comprends pas à quoi ça sert c'est ton problème", c'est au mieux qu'on ne sait pas non plus à quoi ça sert. Au pire que personne ne le sait parce que ça ne sert à rien.

    Voilà voilà voilà.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  11. #11
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2014
    Messages
    72
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Moselle (Lorraine)

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

    Informations forums :
    Inscription : Juin 2014
    Messages : 72
    Par défaut
    Je te l'ai dit, ce que tu fais, ça te regarde. Mais on ne peut pas abandonner un débutant qui tombe sur cette page et penserait que tout ça a un sens. Ça n'en a pas. C'est à ça que sert ce que je dis.
    La chose qui aurait été utile ici pour le débutant dont tu parle est que tu lui laisse un avis constructif qui l'aiderait, au lieu de critiquer et de laisser des avis nuls et sans aucune utilité !
    Un débutant qui tombera sur cette page aura juste vu ton immaturité et ton ego .
    J'ai posé la question sur MON sujet, et heureusement il y avait des gens plus sages et plus compétents qui ont su me répondre et m'orienter.
    J'ai trouvé la solution qu'il me fallait dans MON contexte à moi, où tu n'as rien à y faire d'ailleurs, et je l'ai postée comme n'importe qui l'aurait fait, et en l'occurence ici la solution répond parfaitement au sujet de la discussion (et je ne te demande pas ton avis car je n'en ai pas besoin).

    De toute façon quand je pose la question "à quoi ça sert", si ça sert vraiment à quelque chose eh bien il suffirait de répondre à la question.
    Mais tu te prends pour qui ? un dieu du code ? non, t'en es loin figure toi, très loin.
    Vu ton immaturité et ta condescendence, je ne regrette pas de ne pas avoir répondu à la question comme tu l'aurais souhaité, ça n'aurait servi à RIEN.
    De toute façon, pour moi, tu n'es personne, juste un pauvre type nul qui ne sait pas utiliser sa plume.

    Quand au lieu de répondre on dit "si tu comprends pas à quoi ça sert c'est ton problème", c'est au mieux qu'on ne sait pas non plus à quoi ça sert. Au pire que personne ne le sait parce que ça ne sert à rien.
    Je te rassure, je sais parfaitement à quoi cela sert. Je me ferais un plaisir de l'expliquer à n'importe qui mais pas à toi, car de toute façon ton niveau est tellement bas que tu n'arriveras même pas à comprendre.


    Voilà voilà voilà et encore voilà.

  12. #12
    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 : 45
    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
    Bonjour,

    je me permet d'amener mon petit grin de sel pour corriger un peu tout ce qui ne va pas et pourrait induire un débutant qui passe en erreur (Soyons constructif)

    Tout d'abord ce code, le dernier fournit, ne peut pas être bon, impossible qu'il marche. :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
            Class<T> genericObj;
     
    	Method maMethode = genericObj.getClass().getDeclaredMethod("nomDeMaMethode", null); // null pour dire qu'elle n'a pas de paramètre
    	String result = (String) maMethode.invoke(genericObj, new Object[0]); //new Object[0] pour ne pas mettre null car il attend une liste de params
    genericObj est de type java.lang.Class, il n'a donc pas de méthode "nomDeMaMethode" et le seules méthodes qu'il peux avoir sont listée dans l'api java. En plus, Class est final, donc aucune sous classe ne peut exister. Je vais donc partir du principe que ce que l'on voulais écrire était en fait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
            T genericObj;
    	Method maMethode = genericObj.getClass().getDeclaredMethod("nomDeMaMethode", null); // null pour dire qu'elle n'a pas de paramètre
    	String result = (String) maMethode.invoke(genericObj, new Object[0]); //new Object[0] pour ne pas mettre null car il attend une liste de params

    Ce qui, même si ce n'est pas propre et dans les règle de l'art, a au moins le mérite d'avoir du sens (on recherche à invoquer "nomDeMaMethode" sur genericObj qui est de type T.
    Corrigez moi si j'ai mal compris le problème de départ.
    Du coup, le même problème est présent dans le bout de code de début

    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 class MaClasse <T, M> {
     
    	@Autowired
    	private Class<T> membre1;
     
    	public Class<M> maMethodeQuiRenvoieUnResultat(Class<M> param1) {
               // Je veux pouvoir executer une methode qui est définie dans param1 (exemple cette méthode calcule et renvoie la date d'aujourd'hui+3 jours)
               // ça donnerait : Date d = param1.getDateDansTroisJours();
     
               // ENSUITE :
     
               // executer une méthode de membre1 qui prend une date en paramètre et renvoi un objet de type Class<M>
               // ça donnerait : Class<M> res = membre1.uneMethode(Date d);
            }
    }
    où l'on devrait a priori lire ceci
    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 class MaClasse <T, M> {
     
    	@Autowired
    	private T membre1;
     
    	public M maMethodeQuiRenvoieUnResultat(M param1) {
               // Je veux pouvoir executer une methode qui est définie dans param1 (exemple cette méthode calcule et renvoie la date d'aujourd'hui+3 jours)
               // ça donnerait : Date d = param1.getDateDansTroisJours();
     
               // ENSUITE :
     
               // executer une méthode de membre1 qui prend une date en paramètre et renvoi un objet de type Class<M>
               // ça donnerait :M res = membre1.uneMethode(Date d);
            }
    }
    Que constate-t-on? (encore une fois corrigez si j'ai mal compris le contexte)
    param1 doit disposer d'une méthode getDateDansTroisJours dont la signature est "Date getDateDansTroisJours()"
    membre1 dispose d'une méthode "uneMethode" donc la signature est "M uneMethode(Date)"

    mettons ça en musique. Comme j'ignore l'usage, je vais donner des noms un peu bateau à mes interfaces:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    public interface Generateur {
        Date getDateDansTroisJours();
    }
    public interface Transformateur<M> {
        public M uneMethode(Date date);
    }
    ensuite, le code de la classe deviens
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    public class MaClasse<T extends Transformateur<M>, M extends Generateur > {
     
    	@Autowired
    	private T membre1;
     
    	public M maMethodeQuiRenvoieUnResultat(M param1) {
               return membre1.uneMethode(param1.getDateDansTroisJours());
            }
    }
    et les différents paramètres / injection de notre MaClasse devront implémenter lesdites interfaces.

    Ok, ça c'est la version simple. Notez le lien créé entre le Transformateur et M

    Maintenant je vais émettre 2 hypothèses alternatives possibles qui expliqueraient qu'on a cherché des solutions compliquées au problème.

    La première c'est que le nom de la méthode est inconnu et fait l'objet d'un argument passé en paramètre de MaClasse qu'on ne voit pas dans l'exemple. Si le nom de la méthodes est inconnu, alors effectivement il faut passer par de la réflectivité je craint. Cependant, il faut sérieusement se poser la question de quel design a abouti à cela, car il devrait être extrêmement rare, sauf à designer des outils très générique (genre le coeur de spring), d'avoir besoin de sortir les apis reflectivité. Il vaut toujours mieux se baser sur les surcharges / redéfinitions et interfaces afin que le compilateur soit à même de faire son boulot de validation.

    La seconde hypothèse alternative sur laquelle je vais m'étendre: on connait la méthode, on ignore son type de paramètre mais on sait qu'il est identique au type de paramètre retourné par getDateDansTroisJours dont on ignore aussi le type de retour. Il faut donc ajuster nos interfaces.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    public interface Generateur<X> {
        X getDateDansTroisJours();
    }
    public interface Transformateur<M, X> {
        public M uneMethode(X valeur);
    }
    en on lie tout ça dans MaClasse
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    public class MaClasse<T extends Transformateur<M,X>, M extends Generateur<X>, X> {
     
    	@Autowired
    	private T membre1;
     
    	public M maMethodeQuiRenvoieUnResultat(M param1) {
               return membre1.uneMethode(param1.getDateDansTroisJours());
            }
    }

    Citation Envoyé par lenas_tshaleb Voir le message
    dans mon contexte le paramètre "param1" serait un un Service Springboot donc techniquement je peux faire hériter mes services depuis une classe service mere mais je ne sais si cela est cohérent étant donné que les services ne sont pas liés entre eux.
    C'est une question à débattre. Tu pourrais aussi mettre du code générique dans une interface et l'implémenter dans tous tes services. Vu qu'on ne voit pas concrètement ce que tu essaie de réaliser, c'est une peu compliqué de répondre de manière détaillée.

    Edit: j'ai tappé le code de mémoire, je ne suis pas à l'abris d'un oubli ou d'une erreur

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

Discussions similaires

  1. Comment Executer Une Classe Java Dans Une Page Jsp
    Par yazidi_marwen dans le forum Servlets/JSP
    Réponses: 2
    Dernier message: 10/05/2012, 13h20
  2. comment executer un script perl svp?
    Par nico72 dans le forum Langage
    Réponses: 8
    Dernier message: 13/07/2005, 09h51
  3. Réponses: 4
    Dernier message: 03/12/2004, 11h18
  4. [CR8.5] Comment executer ses propres requetes SQL.
    Par caviar dans le forum SAP Crystal Reports
    Réponses: 5
    Dernier message: 26/10/2004, 20h44
  5. [DEBUTANT]Comment executer un script sql
    Par peaceinpal dans le forum PostgreSQL
    Réponses: 3
    Dernier message: 15/03/2004, 08h44

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