Вот общий способ, используя отражение:
private static Random r = new Random();
public static void callRandomMethod(Object target, Class<?> iface, Object ... arguments) {
List<Method> methods = findFittingMethods(iface, arguments);
Method m = methods.get(r.nextInt(methods.size()));
m.invoke(target, arguments);
}
public List<Method> findFittingMethods(Class<?> iface, Object ... arguments
Method[] allMethods = iface.getMethods();
List<Method> fittingMethods = new ArrayList<Method>();
findMethodLoop:
for(Method candidate : allMethods) {
Class<?>[] argumentTypes = candidate.getArguments();
if(argumentTypes.length != arguments.length) {
continue;
}
// check argument types
for(int i = 0; i < argumentTypes.length; i++) {
if(arguments[i] == null) {
if(argumentTypes[i].isPrimitive()) {
// null can't be passed to a primitive argument.
continue findMethodLoop;
}
else {
// ... but to every other argument type.
continue; // check next argument
}
}
if(argumentTypes[i].isInstance(arguments[i])) {
continue; // check next argument
}
if(argumentTypes[i].isPrimitive()) {
// hack to check if we have the right wrapper class
try {
Array.set(Array.newInstance(argumentTypes[i], 1), 0, arguments[i]);
continue; // check next argument
}
catch(ArrayStoreException ex) {
continue findMethodLoop;
}
}
// wrong type
continue findMethodLoop;
}
// now we found a method which would accept the arguments, put it into the list.
fittingMethods.add(candidate);
}
return fittingMethods;
}
Конечно, если вы будете делать это часто, вы не будете создавать список методов для каждого вызова, а только один раз и будете использовать его потом. (И если у вас есть только известный интерфейс с небольшим количеством методов, используйте вместо него оператор switch
, как рекомендовали другие).