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

API standards et tierces Java Discussion :

Reflect JAVA: Connaître dynamiquement le type primitif associé


Sujet :

API standards et tierces Java

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    51
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 51
    Par défaut Reflect JAVA: Connaître dynamiquement le type primitif associé
    Bonjour,

    J'ai le problème suivant que j'arrive pas encore à résoudre:


    J'ai une méthode de l'API de BerkeleyDB Java Edition qui s'appelle
    TupleOutput.writeLong(long l) que j'aimerais exécuter dynamiquement. Je dispose du type java.lang.Long en tant que classe dans une variable nommée type.
    Ce que je fais:
    • Je récupère le nom de cette classe que je tronque pour n'avoir que le nom "Long", que je stocke dans une variable nommée name.
    • Là survient mon problème. Ce code:
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      Method m = TupleOutput.class.getMethod("write"+name,????? )
      montre je devrais mettre Long.TYPE à la place de ????? pour gérer le type primitif long sous-jacent au type Long!

    Mais comme, ce qui se fait pour le type Long peut aussi bien se passer pour les autres (writeInt(int i), writeFloat(float f)...), j'aimerais savoir si par quelque moyen, il serait possible de récupérer dynamiquement le type primitif caché dans la variable type initiale, sans avoir à se servir des conditions IF, ou sans avoir à utiliser un map où on ferait la correspondance entre les types objets et primitifs ....

    Je vous remercie.

  2. #2
    Membre chevronné Avatar de spekal
    Inscrit en
    Mai 2005
    Messages
    502
    Détails du profil
    Informations forums :
    Inscription : Mai 2005
    Messages : 502
    Par défaut
    Avec la reflection, tout part du nom de la chose que tu veux manipuler. Si tu as le nom, tu as tout.

    C'est le même principe pour les types simples. À partir de leur nom, tu as très naturellement leur type, fut-il simple.

    Exemple avec length (le nom de la méthode length) de String, qui renvoie un int :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    System.out.println("type de length : "+String.class.getMethod("length", null).getReturnType());
    ... t'affiche int.

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    51
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 51
    Par défaut
    Je comprends et je t'en remercie.
    neanmoins mon problème c'est le second argument.
    a priori la variable type peut prendre une valeur de classe parmi les 8 ou 9 types de classe objet associés aux types primitifs.

    Ce second argument dans mon cas serait LE type primitif associé à la classe d'emballage.

    Exple : A Integer.class correspondra Integer.TYPE;
    A Long.class correspondra Long.TYPE;
    etc.

    Le problème c'est, comment trouver automatiquement la valeur primitive Class.TYPE lorsque je dispose de Class? (sous-entendu Class.TYPE existe pour Class).

  4. #4
    Membre chevronné Avatar de spekal
    Inscrit en
    Mai 2005
    Messages
    502
    Détails du profil
    Informations forums :
    Inscription : Mai 2005
    Messages : 502
    Par défaut
    J'avais bien compris confusément que ton problème était le second paramètre.

    Si je réponds directement à ta question, la classe qui correspond à un type primitif est /Primitif/.TYPE ; par exemple, pour boolean, c'est Boolean.TYPE.

    Mais j'ai peur que cela te laisse sur ta faim... Peut être seras-tu plus heureux en ayant automatiquement le nom qui correspond à ce type ; pour cela, si tu as la classe, il suffit de faire le classe.toString(). C'est bien indiqué dans le javadoc que, pour les types primitifs, cela renvoie juste le nom du type primitif. Tu peux tester au préalable si c'est un type primitif avec classe.isPrimitive().

    Et pour savoir si une classe correspond à une autre, il suffit de faire le test d'égalité. Par exemple if (ClasseDeToto == Boolean.TYPE)... alors c'est un booléen.

    Cependant, mon impression générale est que ce n'est pas forcément la meilleure approche, d'où le fait que j'insistais sur la recherche du nom, donc, dans ton cas, du nom de ce paramètre (ou au moins sa position dans la signature de la méthode). Mais si tu l'as déjà, alors le classe.toString() te suffira peut être.

    N'hésites pas à en dire plus si cette proposition ne résoud rien.

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    51
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 51
    Par défaut
    class.toString renvoie un truc du genre "class java.lang.String" pour la classe d'emballage Strinng.

    Je crois que je vais plutot me faire une map immuable, avec pour clés les classes d'emballage et en valeur leur types primitifs.

  6. #6
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 897
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Nouvelle-Calédonie

    Informations professionnelles :
    Activité : Information Technologies Specialist (Scientific Computing)
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Août 2005
    Messages : 6 897
    Billets dans le blog
    54
    Par défaut
    Depuis que je fais du Java j'ai toujours utilise les classes et valeur objets pour faire de la reflection sur des methodes prenant des valeurs literrales. De plus je te rappelle egalement que quand tu veux invoquer la methode (Method.invoke()) , le passage des parametres necessitent de toute facon d'avoir des Object (idem pour la valeur de retour de la methode) => donc utiliser Long.class et convertir tes long en Long (resp sur les autres types litteraux).
    Merci de penser au tag quand une réponse a été apportée à votre question. Aucune réponse ne sera donnée à des messages privés portant sur des questions d'ordre technique. Les forums sont là pour que vous y postiez publiquement vos problèmes.

    suivez mon blog sur Développez.

    Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning. ~ Rich Cook

  7. #7
    Membre averti
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    51
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 51
    Par défaut
    Citation Envoyé par bouye
    Depuis que je fais du Java j'ai toujours utilise les classes et valeur objets pour faire de la reflection sur des methodes prenant des valeurs literrales. De plus je te rappelle egalement que quand tu veux invoquer la methode (Method.invoke()) , le passage des parametres necessitent de toute facon d'avoir des Object (idem pour la valeur de retour de la methode) => donc utiliser Long.class et convertir tes long en Long (resp sur les autres types litteraux).
    J'ai effectivement des objects Long. Mais je veux invoquer la méthode d'une bibliothèque qui attend en argument le type primitif long.

    Je te vois dire qu'il faut utiliser l'auto unboxing de Java5 pour faire passer le Long en long.

    Mais mon problème c'est que j'ai une map (mapTypes) qui prend en clé des nom de champs et en valeurs les types (classes d'emballages) de ces champs. J'ai aussi une mapValeur de même taille que mapTypes avec les mêmes noms de champ et qui contient des objets (instances de classes d'emballages) compatibles avec les types de mapTypes. Et de l'autre côté la classe X de la bibliothèque de BerkeleyDB qui me propose selon le type à manipuler des methodes comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    X.writeInt(int), X.writeLong(long), X.writeByte(byte), X.writeBoolean(boolean) etc.
    Je veux pas faire de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    if(mapTypes.get(key)==Integer.class)
        int value = mapValue.get(key);
        X.writeInt(int); //etc
    J'aimerais itérer sur mapTypes, recuperer le type, identifier dans la X de bibliotheque BerkeleyDB la methode correspondante parmi les X.write... grace à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Method m = X.class.getMethod("write"+valeurType,type_primitif_correspondant)
    et ce n'est ensuite que je peux invoquer cette methode m:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    m.invoke(instance_de_X,valeur_compatible_argument_de_m)
    Je pêche que la recherche de la signature de la methode dans la classe X. Ma question est alors de savoir si je peux avoir le type primitif correspondant à la classe d'emballage donnée dans ce code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Method m = X.class.getMethod("write"+valeurType,type_primitif_correspondant)
    Voilà.

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

    Citation Envoyé par TravelMate
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Method m = X.class.getMethod("write"+valeurType,type_primitif_correspondant)
    Lorsque tu veux exécuter ce code, quel sont les données que tu as en entré ??? Que vallent valeurTypeet type_primitif_correspondant et quel est leurs type exact ???

    a++

  9. #9
    Membre averti
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    51
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 51
    Par défaut
    Citation Envoyé par adiGuba
    Salut,


    Lorsque tu veux exécuter ce code, quel sont les données que tu as en entré ??? Que vallent valeurTypeet type_primitif_correspondant et quel est leurs type exact ???

    a++
    Valeur type peut prendre une valeur parmi Integer.class, Boolean.class, Long.class etc ... (tous les types parmi les classes d'emballages de types primitifs JAVA).

    Et quand je veux exécuter cette methode je ne dispose que de la variable classe (par exple la classe java.lang.Long) parmi les 8 valeurType possibles.
    J'ai formé avec cela la chaîne à rajouter à "write", puis il ne reste plus que le type de l'argument à gérer. J'aimerais pouvoir récupérer automatiquement à partir de valeurType ou de la variable classe (par exple la classe java.lang.Long) le type primitif correspondant pour compléter la signature de la méthode.

  10. #10
    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
    Je ne suis pas sûr d'avoir compris...

    Tu voudrais obtenir le type primitifs correspond à la classe Wrapper.
    C'est à dire si valeurType == java.lang.Long.class, tu voudrais avoir obtenir java.lang.Long.TYPE ? C'est ca ?

    Dans ce cas tu peux utiliser la reflection pour cela, en recherchant le champs static TYPE dans le class :

    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
    33
    34
    35
        /**
         * Retourne le type primitive associé à la classe Wrapper.
         * Exemple :
         * getPrimitive(Long.class) --> Long.TYPE
         * getPrimitive(Long.TYPE) --> Long.TYPE
         * getPrimitive(Integer.class) --> Integer.TYPE
         * getPrimitive(String.class) --> null
         * 
         * @param c
         * @return Le type primitif associé à la classe 'c',
         * ou null si 'c' n'est pas une classe Wrapper...
         */
        public static Class getPrimitive(Class c) {
            Class result = null;
            if (c.isPrimitive()) {
                // S'il s'agit déjà d'un type primitive
                // On retourne l'objet directement
                result = c;
            } else {
                // Sinon on recherche le champ static TYPE par reflection :
                try {
                    Field field = c.getDeclaredField("TYPE");
                    Object object = field.get(null);
                    // Et on vérifie son type et sa valeur :
                    if ( (object instanceof Class) && ((Class)object).isPrimitive() ) {
                        result = (Class) object;
                    }
                } catch (Exception e) {
                    // On ignore les exceptions
                    // on retourne null
                    result = null;
                }
            }
            return result;
        }
    a++

  11. #11
    Membre averti
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    51
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 51
    Par défaut
    Merci, j'avais déjà vu des methodes de ce type. Mais je cherchais à savoir si un autre moyen existait.

    je vais donc me résigner à utiliser ta solution.

  12. #12
    Membre à l'essai
    Profil pro
    Inscrit en
    Août 2006
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 6
    Par défaut
    Citation Envoyé par TravelMate
    J'ai une méthode de l'API de BerkeleyDB Java Edition qui s'appelle TupleOutput.writeLong(long l) que j'aimerais exécuter dynamiquement. Je dispose du type java.lang.Long en tant que classe dans une variable nommée type.
    A moins que je n'ai lu trop vite, tu as déjà l'objet que tu cherches : Long.TYPE retourne le singleton de Class<Long>, ce qui est précisément l'objet contenu dans ta variable 'type'.
    Donc, il te suffit de faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Method m = TupleOutput.class.getMethod("write"+name, type)
    ça devrait suffire

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

Discussions similaires

  1. Changer la nature d'un projet Java en projet de type Web Dynamique ?
    Par shaun_the_sheep dans le forum Eclipse Java
    Réponses: 10
    Dernier message: 14/01/2010, 16h50
  2. Reflection et type primitif
    Par Buendon dans le forum API standards et tierces
    Réponses: 16
    Dernier message: 22/08/2007, 18h44
  3. [prog dynamique]Constructeur avec type primitif
    Par -=Spoon=- dans le forum Langage
    Réponses: 2
    Dernier message: 16/12/2004, 10h33
  4. [LG]Problême Variable dynamique de types différents
    Par pierrOPSG dans le forum Langage
    Réponses: 2
    Dernier message: 29/04/2004, 16h01

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