vendredi 17 avril 2015

Java et la réflexion [2/4]

Les méthodes
Récupération des méthodes public
Afin de récupérer les méthodes publics d'une classe, il faut utiliser la méthode getMethods(). Cette méthode ne retourne pas les méthodes privées !
Vous récupérez un object Method. Cet objet récupéré, va permettre d'appeler la méthode avec ou sans paramètre, connaitre les types de paramètres attendus...
Récupération des paramètres des méthodes
Avec Java 8, il est très facile de savoir si une méthode attend des paramètes ou non avec la méthode Method.getParameterCount().
Si la méthode attend des paramètres, il est possible de les récupérer via la méthode getParameterTypes().
Détecter si le paramètre est de type primitif
Une fois le paramètre obtenu, il est important de savoir si ce paramètre est un primitif au non, afin de convertir correctement la donnée à entrer.
Partons du postulat que nous avons une chaine de caracètre que nous souhaitons convertir vers un type primitif :
// L'objet sur lequel on fait de la reflexion
Object obj = ...;
// Le setter a utiliser
Method setter = ....;
// On suppose qu'il n'y a paramètre au setter
Class parameter = setter.getParameterTypes()[0];

if (parameter.isPrimitive()) {
    if (parameter == Boolean.TYPE) {
        m.invoke(obj, Boolean.valueOf(value));
    } else if (parameter == Byte.TYPE) {
        m.invoke(obj, Byte.valueOf(value));
    } else if (parameter == Character.TYPE) {
        m.invoke(obj, Character.valueOf(value.substring(0, 1));
    } else if (parameter == Short.TYPE) {
        m.invoke(obj, Short.valueOf(value));
    } else if (parameter == Integer.TYPE) {
        m.invoke(obj, Integer.valueOf(value));
    } else if (parameter == Long.TYPE) {
        m.invoke(obj, Long.valueOf(value));
    } else if (parameter == Double.TYPE) {
        m.invoke(obj, Double.valueOf(value));
    } else if (parameter == Float.TYPE) {
        m.invoke(obj, Float.valueOf(value));
    }
}
Détecter si le paramètre est de type tableau
Pour savoir s'il s'agit d'un tableau en entrée de la méthode, il est possible d'utiliser la méthode isArray() sur le paramètre, comme pour isPrimitive()
Détecter si le paramètre est une énumération
Pour savoir s'il s'agit d'un enum, il est possible d'utiliser la méthode isEnum() sur le parametre, comme pour isPrimitive()
Détecter si le paramètre est de type List/Map...
A présent, pour savoir si le paramètre est un list, la solution est simple, comparer avec le classe en question, comme nous l'avons fait avec les primitifs. A savoir :
    if (parameter == List.class)
Récupération du générique de la liste
Pour récupérer le type du générique de la liste, là pas de longue explication, c'est en recherchant sur internet qu'on trouve des pistes, puis les expérimentations font le reste. Pour vous faire gagner du temps, voilà la solution :
Type[] parameter = setter.getGenericParameterTypes();

Type type = ((ParameterizedTypeImpl) parameter[0]).getActualTypeArguments()[0];

return Class.forName(type.getTypeName());
Oui, ça ne s'invente pas. A retenir, ((ParameterizedTypeImpl) parameter[0]) veut dire qu'on prend le premier paramettre de la méthode, getActualTypeArguments()[0] indique qu'on prend le premier paramètre générique. Et oui, pour une Map, il faudra prendre les 2 premiers.

Aucun commentaire:

Enregistrer un commentaire