Suppose I have three methods inside a given type (class/interface):
public void foo(Integer integer);
public void foo(Number number);
public void foo(Object
Given the constraints that: a) the type of the parameter is only known at runtime, and b) there is only one parameter, a simple solution can be just walking up the class hierarchy and scanning the implemented interfaces like in the following example.
public class FindBestMethodMatch {
public Method bestMatch(Object obj) throws SecurityException, NoSuchMethodException {
Class> superClss = obj.getClass();
// First look for an exact match or a match in a superclass
while(!superClss.getName().equals("java.lang.Object")) {
try {
return getClass().getMethod("foo", superClss);
} catch (NoSuchMethodException e) {
superClss = superClss.getSuperclass();
}
}
// Next look for a match in an implemented interface
for (Class> intrface : obj.getClass().getInterfaces()) {
try {
return getClass().getMethod("foo", intrface);
} catch (NoSuchMethodException e) { }
}
// Last pick the method receiving Object as parameter if exists
try {
return getClass().getMethod("foo", Object.class);
} catch (NoSuchMethodException e) { }
throw new NoSuchMethodException("Method not found");
}
// Candidate methods
public void foo(Map map) { System.out.println("executed Map"); }
public void foo(Integer integer) { System.out.println("executed Integer"); }
public void foo(BigDecimal number) { System.out.println("executed BigDecimal"); }
public void foo(Number number) { System.out.println("executed Number"); }
public void foo(Object object) { System.out.println("executed Object"); }
// Test if it works
public static void main(String[] args) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
FindBestMethodMatch t = new FindBestMethodMatch();
Object param = new Long(0);
Method m = t.bestMatch(param);
System.out.println("matched " + m.getParameterTypes()[0].getName());
m.invoke(t, param);
param = new HashMap();
m = t.bestMatch(param);
m.invoke(t, param);
System.out.println("matched " + m.getParameterTypes()[0].getName());
}
}