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
| /**
* Indique si l'instance 'argValue' est compatible avec 'argType'.
* C'est à dire :
*
* Si 'argType' est un type primitif, 'argValue' doit être du type
* correspondant (int - Integer...).
*
* Si 'argType' est un type standard, 'argValue' peut être null
* ou bien correspondre à un type fils.
* @param argType Le type à vérifier
* @param argValue L'instance qui doit correspondre au type
* @return true si l'instance est compatible / false sinon.
*/
private static boolean isCompatible(Class<?> argType, Object argValue) {
if (argType.isPrimitive()) {
// On a affaire à un type primitif :
// On refuse les valeurs null
if (argValue==null) return false;
// Et n doit vérifier que 'argValue' correspondent au type wrapper
if (argType==byte.class) return argValue.getClass()==Byte.class;
if (argType==boolean.class) return argValue.getClass()==Boolean.class;
if (argType==char.class) return argValue.getClass()==Character.class;
if (argType==short.class) return argValue.getClass()==Short.class;
if (argType==int.class) return argValue.getClass()==Integer.class;
if (argType==long.class) return argValue.getClass()==Long.class;
if (argType==float.class) return argValue.getClass()==Float.class;
if (argType==double.class) return argValue.getClass()==Double.class;
// Sinon on retourne false (on ne devrait pas arriver ici)
return false;
} else {
// On a affaire à un type quelquonque :
// On accepte soit null, soit une valeur de même instance :
return argValue==null || argType.isInstance(argValue);
}
}
/**
* Invoque une méthode sur une instance, en utilisants le type des paramètres
* pour retrouver la bonne méthode.
* @param instance L'instance de l'objet
* @param methodName Le nom de la méthode
* @param args La liste des paramètres
* @return Le retour de la méthode,
* @throws NoSuchMethodException
* @throws IllegalArgumentException
* @throws IllegalAccessException
* @throws InvocationTargetException
*/
public static Object invoke(final Object instance, final String methodName, final Object...args)
throws NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
final Class<?> clazz = instance.getClass();
// On parcours le tableau des méthodes :
for (final Method method : clazz.getMethods()) {
// Si le nom de la méthode correspond :
if (method.getName().equals(methodName)) {
Class<?>[] argsType = method.getParameterTypes();
// Et que le nombre de paramètres est identique :
if (argsType.length==args.length) {
boolean ok = true;
// On vérifie le type de chaques paramètres :
for (int i=0; i<argsType.length; i++) {
ok = ok && isCompatible(argsType[i], args[i]);
}
// Si tout est OK on execute la
if (ok) {
return method.invoke(instance, args);
}
}
}
}
// Sinon on génère une exception avec un message de la forme 'NomClasse.nomMethode(argsType)'
StringBuilder sb = new StringBuilder(clazz.getName());
sb.append(".").append(methodName).append("(");
for(Object obj : args) {
sb.append(obj==null?"null":obj.getClass().getName());
sb.append(", ");
}
sb.delete(sb.length()-2, sb.length());
sb.append(")");
throw new NoSuchMethodException(sb.toString());
} |
Partager