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 :

Probleme avec fonction generique


Sujet :

Langage Java

  1. #1
    Membre actif
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Avril 2010
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Chercheur en informatique

    Informations forums :
    Inscription : Avril 2010
    Messages : 12
    Par défaut Probleme avec fonction generique
    Bonjour,
    J'ai une classe AnnotationSet, qui herite de HashSet et qui a pour fonction d'etre au courant du type parametre. Par example, new AnnotationSet<String>().printGenericType() affiche String.

    J'ai plusieurs types d'annotations, que j'ai regroupe dans une map(HashMap<Class<?>, AnnotationSet> annotations). Pour ajouter
    de type String, j'ai implemente la fonction void addAnnotation(String annotation), qui fonctionne parfaitement (pour l'exemple, elle affiche le type de l'annotation). Mais comme les annotations sont generiques, la fonction pour en ajouter se doit de l'etre egalement, d'ou <T> void addAnnotation(T annotation). Et la, c'est le drame: divorse entre mon AnnotationSet<T> et sont type parametre <T> qui ne se reconnaissent plus


    Y-a-t-il une solution a ce pb? Merci

    PS: c'est quand meme un peu le bordel les generiques en Java...

    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
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
     
    public static void main(String[] args) {	
    	HashMap<Class<?>, AnnotationSet>	annotations;
    	// [...] some random code
    	addAnnotation(new String("stuff"));		// Works fine: displays String
    	addAnnotation(new Integer(1));			// NOT WORKING: displays UndeterminedType
    }
     
    /**
     * Adds a generic annotation
     * @Deprecated not working
     */
    public <T> void addAnnotation(T annotation) {
    	if (!annotations.containsKey(annotation.getClass()))
    		annotations.put(annotation.getClass(), new AnnotationSet<T>(this) {}); // Notice the trivial anonymous class
    	annotations.get(annotation.getClass()).add(annotation);
    	annotations.get(go.getClass()).printGenericType();
    }
    /**
     * Add an annotation of type String
     */
    public void addAnnotation(String annotation) {
    	if (!annotations.containsKey(annotation.getClass()))
    		annotations.put(annotation.getClass(), new AnnotationSet<String>(this) {}); // Notice the trivial anonymous class
    	annotations.get(annotation.getClass()).add(annotation);
    	annotations.get(go.getClass()).printGenericType();
    }
     
    public class AnnotationSet<T> extends HashSet<T> {
    	/** To keep track of the parameterized type */
    	private Class<?>				genericType;
    	/** Object being annotated */
    	private Object		parent		= null;
     
    	/**
             * Class constructor.    *
             * @param parent Object being annotated
             */
    	public AnnotationSet(WarehouseObject parent) {
    		super();
    		this.parent = parent;
     
    		// From http://www.artima.com/weblogs/viewpost.jsp?thread=208860
    		// this.genericType now contains the Class T
    		this.genericType = ReflectionUtils.getTypeArguments(AnnotationSet.class, getClass()).get(0);
    	}
     
    	public void printGenericType() {
    		try {
    			System.out.println(genericType.getSimpleName());
    		} catch (Exception e) {
    			System.out.println("UndeterminedType");
    		}
    	}
    } // eo AnnotationSet

  2. #2
    Membre éclairé Avatar de Jacobian
    Inscrit en
    Février 2008
    Messages
    425
    Détails du profil
    Informations forums :
    Inscription : Février 2008
    Messages : 425
    Par défaut
    - déjas lorsque tu fais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    addAnnotation(new Integer(1));
    c'est normale que vous auriez une erreur de type :
    type String attendue au lieu de Integer

    - aussi je comprend pas comment tu fait appel a une methode static dans une autre qui n'est pas static

  3. #3
    Membre actif
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Avril 2010
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Chercheur en informatique

    Informations forums :
    Inscription : Avril 2010
    Messages : 12
    Par défaut
    Citation Envoyé par Jacobian Voir le message
    - déjas lorsque tu fais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    addAnnotation(new Integer(1));
    c'est normale que vous auriez une erreur de type :
    type String attendue au lieu de Integer

    - aussi je comprend pas comment tu fait appel a une methode static dans une autre qui n'est pas static

    Pour garder le code dans mon topic concis, je ne montre que des fragments de code qui sont pertinents. L'assemblage n'est pas des plus heureux, mais n'existe pas reellement. Dans cette lignee, selon les executions, l'une des variantes de addAnnotation() est commentee.

    Ceci etant, addAnnotation(new Integer(1)) fait bien appel a <T> void addAnnotation(T annotation), avec T=Integer, le bug n'est pas a ce niveau.

  4. #4
    Membre éclairé
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    802
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 802
    Par défaut
    Il y a pas mal de choses qui ne collent pas dans ton code, et en particulier, tu as un problème d'architecture. Mais concernant juste les Générics, le type générique T déclaré pour la classe AnnotationSet et le type générique T déclaré pour la méthode addAnnotation() ne sont pas le même type, bien qu'ils portent la même lettre. C'est comme lorsqu'on déclare une variable, elle a une portée limitée, et deux variables peuvent avoir le même nom si elles ne sont pas dans la même portée (méthode ou classe).

  5. #5
    Membre actif
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Avril 2010
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Chercheur en informatique

    Informations forums :
    Inscription : Avril 2010
    Messages : 12
    Par défaut
    Citation Envoyé par verbose Voir le message
    Il y a pas mal de choses qui ne collent pas dans ton code, et en particulier, tu as un problème d'architecture.
    Tu pourrais détailler stp?

    Citation Envoyé par verbose Voir le message
    Mais concernant juste les Générics, le type générique T déclaré pour la classe AnnotationSet et le type générique T déclaré pour la méthode addAnnotation() ne sont pas le même type, bien qu'ils portent la même lettre. C'est comme lorsqu'on déclare une variable, elle a une portée limitée, et deux variables peuvent avoir le même nom si elles ne sont pas dans la même portée (méthode ou classe).
    Cela tombe sous le sens... mais comment faire alors pour avoir une fonction addAnnotation() générique?

  6. #6
    Membre confirmé
    Inscrit en
    Juillet 2008
    Messages
    29
    Détails du profil
    Informations forums :
    Inscription : Juillet 2008
    Messages : 29
    Par défaut
    Merci nous joindre les quelques classes coeur de ton problème pour qu'on puisse t'aider...

  7. #7
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 586
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 586
    Par défaut
    La méthode décrite en http://www.artima.com/weblogs/viewpo...?thread=208860 ne peut pas marcher.
    L'exemple d'utilisation est un TypeAwareArrayList<String>, pas un TypeAwareArrayList<T>. Là est toute la différence.

    Oublie cette méthode, elle ne va pas t'avancer. Vire ces conneries de new AnnotationSet<T>(this){} et de ReflectionUtils.getTypeArguments().

    À la place, passe toi-même simplement l'objet Class qui sert de paramètre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    public AnnotationSet(WarehouseObject parent, Class<T> type) {
      super();
      this.genericType = type;
      // constructeur
    }
    Pour ça, modifie

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    public <T> void addAnnotation(T annotation)
    en

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    public <T> void addAnnotation(T annotation, Class<T> type)
    Ou alors appelle juste annotation.getClass(), mais cela renverra un Class<? extends T>, pas un Class<T>, donc il faut que le constructeur de AnnotationSet accepte un Class<? extends T>... Ce qui est mal. Donc va plutôt vers ma première idée.

    Citation Envoyé par sethlegoauld
    PS: c'est quand meme un peu le bordel les generiques en Java...
    Hélas. Conséquence malheureuse de l'avoir ajouté à de l'existant au lieu de l'avoir eu dès le départ.
    Mais bon, tu cherches les ennuis, aussi. Aller chercher un truc comme ReflectionUtils.getTypeArguments(), à aucun moment tu t'es dit que si tu étais censé faire ça, ça prendrait moins d'une ligne, non ?
    L'alarme "bon, manifestement, je suis pas sur la bonne voie" aurait dû être assourdissante.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  8. #8
    Membre actif
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Avril 2010
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Chercheur en informatique

    Informations forums :
    Inscription : Avril 2010
    Messages : 12
    Par défaut
    Citation Envoyé par thelvin Voir le message
    À la place, passe toi-même simplement l'objet Class qui sert de paramètre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    public AnnotationSet(WarehouseObject parent, Class<T> type) {
      super();
      this.genericType = type;
      // constructeur
    }
    Pour ça, modifie

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    public <T> void addAnnotation(T annotation)
    en

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    public <T> void addAnnotation(T annotation, Class<T> type)
    OKI merci. J'avais essaye ca aussi par le passe, mais je voulais essayer d'utiliser cette methode (ReflectionUtils.getTypeArguments()) car elle permet d'eviter de passer Class<T> en argument, ce qui n'est pas ideal non plus. Mais bon, quand le remede devient pire que le mal d'origine...

    Merci en tout cas

  9. #9
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 586
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 586
    Par défaut
    Citation Envoyé par sethlegoauld Voir le message
    je voulais essayer d'utiliser cette methode (ReflectionUtils.getTypeArguments()) car elle permet d'eviter de passer Class<T> en argument
    Elle n'évite rien du tout, au contraire elle impose compile-time de définir le type concret de T.
    En gros, ce à quoi elle est censée servir n'est pas ton cas. L'auteur avait une autre idée en tête. (Qui ne me semble pas spécialement bonne non plus.)
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  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
    Citation Envoyé par thelvin Voir le message
    Elle n'évite rien du tout, au contraire elle impose compile-time de définir le type concret de T.
    Plus précisément elle génère une classe fille anonyme (voir plus) pour chaque type paramétré :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    new AnnotationSet<String>(this) {}); // Notice the trivial anonymous class
    Bref cela multiplie le bytecode par la création de plusieurs classes anonymes inutilement...



    Si tu as vraiment besoin du type précis, il est préférable de le passer via un Class<T> comme indiqué par thelvin.

    Au fait, pourquoi as-tu besoin de connaitre précisément le type ?


    a++

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

Discussions similaires

  1. [Mail] probleme avec fonction mail() !!!
    Par H-bil dans le forum Langage
    Réponses: 6
    Dernier message: 20/06/2006, 00h45
  2. C++ - Probleme avec fonction virtuelle
    Par vdumont dans le forum C++
    Réponses: 1
    Dernier message: 20/03/2006, 21h49
  3. probleme avec fonctions
    Par Burinho dans le forum C
    Réponses: 8
    Dernier message: 29/12/2005, 22h28
  4. Réponses: 17
    Dernier message: 24/03/2005, 13h24
  5. [langage] problème avec fonction read
    Par domidum54 dans le forum Langage
    Réponses: 2
    Dernier message: 30/03/2004, 21h42

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