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 :

Comment instancier un objet paramétré par réflexion ?


Sujet :

Langage Java

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Février 2009
    Messages
    75
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 75
    Points : 54
    Points
    54
    Par défaut Comment instancier un objet paramétré par réflexion ?
    Bonjour,

    J'ai une classe :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    public class ClasseMere {
    	private Map<String, ClasseFille1> map1; // Probablement une HashMap
    	private Map<Integer, ClasseFille2> map2; // Probablement une HashMap
    	private ClasseFille3<ClasseFille4, ClasseFille5> classeFille3;
     
    	// les assesseurs associés
    }
    Je voudrai écrire une méthode qui instancie map1 et map2 par réflexion en fonction du type paramétré.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    public void populate() {
    	for (Field field : classeMere.getClass().getDeclaredFields()) {
    		// Instanciation de l'objet correspondant au field et je ne sais pas comment écrire cette ligne de code
     
    		// Remplissage de la map
     
    		// Appel du setter de la map correspondante
    	}
    }

  2. #2
    Membre habitué
    Profil pro
    Opération
    Inscrit en
    Décembre 2012
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Opération

    Informations forums :
    Inscription : Décembre 2012
    Messages : 91
    Points : 188
    Points
    188
    Par défaut
    Dans la méthode populate(), classeMere est, je suppose type ClasseMere.
    Dans ce cas le type des champs map1 et map2 sont des interfaces (peut-être ClasseFille3 aussi). Il ne sera donc pas possible d'en créer des instances ...
    Je ne comprends trop le but de la ' méthode qui instancie map1 et map2 par réflexion en fonction du type paramétré.'
    Pourquoi ne pas créer vos champs normalement : classeMere.map1 = new HashMap<>(); ?

  3. #3
    Modérateur
    Avatar de Gugelhupf
    Homme Profil pro
    Analyste Programmeur
    Inscrit en
    Décembre 2011
    Messages
    1 320
    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 320
    Points : 3 741
    Points
    3 741
    Billets dans le blog
    12
    Par défaut
    Salut sql_ingorant, tu peux tu peux récupérer le type générique de ton field (ParametrizedType), puis le décortiquer pour récupérer le type de tes key et value de ta Map.
    Je t'invite à voir cet exemple (méthode Form#fillField).
    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

  4. #4
    Modérateur

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

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 551
    Points : 21 607
    Points
    21 607
    Par défaut
    Ouais enfin, en ce qui concerne instancier la Map, ses paramètres ça nous sert à rien de les chercher par réflexion.

    - Soit on les connaissait déjà et on fait un truc genre Map<String, ClasseFille1> laMap = new HashMap<>(); .

    - Soit on les connaît pas à l'avance, et dans ce cas on ne peut pas être type-safe, donc ils ne servent à rien et on fait juste Map<?, ?> laMap = new HashMap<Object, Object>(); .

    Il reste effectivement, que quand on se retrouve à instancier un champ de type Map, il va falloir choisir une implémentation de Map, comme par exemple HashMap. Impossible d'instancier directement Map, qui est une interface.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Février 2009
    Messages
    75
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 75
    Points : 54
    Points
    54
    Par défaut
    Citation Envoyé par thelvin Voir le message
    Impossible d'instancier directement Map, qui est une interface.
    Oui, on est d'accord.

    Mais en instanciant l'implémentation via newInstance(), il faut caster car les types paramétrés ne sont que disponible au runtime. N'est-il pas possible de mettre autre chose que (HashMap<Object, Object>)HashMap.newInstance() si on connait le type de Field à passer au cast de HashMap ?

  6. #6
    Modérateur

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

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 551
    Points : 21 607
    Points
    21 607
    Par défaut
    Je ne crois pas, mais plus important : je ne vois pas à quoi ça servirait. Si tu peux m'éclairer, j'aurai peut-être une réponse plus utile.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  7. #7
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Citation Envoyé par sql_ignorant Voir le message
    Je voudrai écrire une méthode qui instancie map1 et map2 par réflexion en fonction du type paramétré.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    public void populate() {
    	for (Field field : classeMere.getClass().getDeclaredFields()) {
    		// Instanciation de l'objet correspondant au field et je ne sais pas comment écrire cette ligne de code
     
    		// Remplissage de la map
     
    		// Appel du setter de la map correspondante
    	}
    }
    Grosso modo
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    public void populate() {
    	for (Field field : classeMere.getClass().getDeclaredFields()) {
                    if (field.getType() == Map.class){
                        field.set(tonObjet,new HashMap<Object,Object>();
                    }
    	}
    }
    Les paramètre n'ont aucun intérêt dans le réflection, le compilateur ne peux pas checker l'introspection et les types générique ne servent que au compilateur.

  8. #8
    Membre du Club
    Profil pro
    Inscrit en
    Février 2009
    Messages
    75
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 75
    Points : 54
    Points
    54
    Par défaut
    Ca donne un truc comme ça :

    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
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    	public T convertFromModel(S model, T bean) throws InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException, ClassNotFoundException {
    		for (Field field : model.getClass().getDeclaredFields()) {
    		        Method getter = getGetter(model, field);
    		        Object convertedField = null;
    			    if (Map.class.isAssignableFrom(field.getType())) {
    			        convertedField = convertMap((Map<Object, Object>)getter.invoke(model, null));
    			    }
    			    else if (Collection.class.isAssignableFrom(field.getType())) {
                        convertedField = convertCollection((Collection<Object>)getter.invoke(model, null));
                    }
    			    else {
    			        convertedField = convertSimpleObject(getter.invoke(model, null));
    			    }
                    Method setter = getSetter(bean, field);
                    setter.invoke(bean, convertedField);
    		}
     
    		return bean;
    	}
     
    	private Map<?, ?> convertMap(Map<?, ?> map) throws IllegalAccessException, InstantiationException {
    	    Map<Object, Object> convertedMap = null;
     
    	    if (map != null) {
    	        convertedMap = (Map<Object, Object>)map.getClass().newInstance();
     
    	        for (Map.Entry<Object, Object> entry : ((Map<Object, Object>)map).entrySet()) {
    	            Object convertedKey = null;
     
                    if (entry.getKey() instanceof Map) {
                        convertedKey = convertMap((Map)entry.getKey());
                    }
                    else if (entry.getKey() instanceof Collection) {
    	                convertedKey = convertCollection((Collection)entry.getKey());
    	            }
    	            else {
    	                convertedKey = convertSimpleObject(entry.getKey());
    	            }
     
    	            Object convertedValue = null;
    	            if (entry.getValue() instanceof Map) {
    	                convertedValue = convertMap((Map)entry.getValue());
                    }
                    else if (entry.getValue() instanceof Collection) {
    	                convertedValue = convertCollection((Collection)entry.getValue());
                    }
                    else {
                        convertedValue = convertSimpleObject(entry.getValue());
                    }
    	            convertedMap.put(convertedKey, convertedValue);
    	        }
    	    }
     
    	    return convertedMap;
    	}
     
    	private Collection<?> convertCollection(Collection<?> collection) throws IllegalAccessException, InstantiationException {
    	    Collection<Object> convertedCollection = null;
     
    	    if (collection != null) {
        	    convertedCollection = (Collection<Object>)collection.getClass().newInstance();
        	    for (Object object : collection) {
        	        Object convertedObject = null;
     
        	        if (object instanceof Map) {
        	            convertedObject = convertMap((Map)object);
                    }
                    else if (object instanceof Collection) {
        	            convertedObject = convertCollection((Collection)object);
        	        }
        	        else {
        	            convertedObject = convertSimpleObject(object);
        	        }
     
        	        convertedCollection.add(convertedObject);
        	    }
    	    }
     
    	    return convertedCollection;
    	}
     
    	private Object convertSimpleObject(Object object) {
    	    // Nothing to do
    	    return object;
    	}

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

Discussions similaires

  1. Réponses: 3
    Dernier message: 24/07/2015, 15h36
  2. Réponses: 8
    Dernier message: 26/03/2011, 20h40
  3. Réponses: 7
    Dernier message: 26/07/2010, 15h25
  4. Réponses: 4
    Dernier message: 23/07/2009, 23h38
  5. Réponses: 6
    Dernier message: 18/01/2006, 16h26

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