Java reflection utility to get method with compatible parameters 

Joined:
03/07/2011
Posts:
57

May 26, 2011 21:16:22    Last update: June 02, 2011 14:39:57
Given a class A:
class A {
    public int doWork(String s, int i, boolean b) {
	System.out.printf("Doing work: string(%s), int(%s), boolean(%s)\n", s, i, b);
	return 1;
    }
}

it is OK to call method doWork with both primitive types and the corresponding wrapping object types:
new A().doWork("Hello", 1, false);
new A().doWork("Hello", new Integer(2), Boolean.TRUE);

However, if you find method by parameter types with Java reflection, the types must match exactly, i.e.,
Class<?> c = Class.forName("A");
// This call finds the doWork method
Method m1 = c.getMethod(
	"doWork", 
	Class.forName("java.lang.String"), 
	int.class,
	boolean.class
);

// This call throws exception
Method m2 = c.getMethod(
	"doWork", 
	Class.forName("java.lang.String"), 
	Class.forName("java.lang.Integer"),
	Class.forName("java.lang.Boolean")
);


This is a utility to find methods with compatible parameter types:
import java.lang.reflect.*;
import java.util.*;

public class ReflectionUtil {
    private static Map<Class,Class> primitiveMap = new HashMap<Class,Class>();
    static {
	primitiveMap.put(boolean.class, Boolean.class);
	primitiveMap.put(byte.class, Byte.class);
	primitiveMap.put(char.class, Character.class);
	primitiveMap.put(short.class, Short.class);
	primitiveMap.put(int.class, Integer.class);
	primitiveMap.put(long.class, Long.class);
	primitiveMap.put(float.class, Float.class);
	primitiveMap.put(double.class, Double.class);
    }

    public static Method getCompatibleMethod(Class c, 
					     String methodName, 
					     Class... paramTypes) {
	Method[] methods = c.getMethods();
	for (int i = 0; i < methods.length; i++) {
	    Method m = methods[i];

	    if (!m.getName().equals(methodName)) {
		continue;
	    }

	    Class<?>[] actualTypes = m.getParameterTypes();
	    if (actualTypes.length != paramTypes.length) {
		continue;
	    }

	    boolean found = true;
	    for (int j = 0; j < actualTypes.length; j++) {
		if (!actualTypes[j].isAssignableFrom(paramTypes[j])) { 
		    if (actualTypes[j].isPrimitive()) {
			found = primitiveMap.get(actualTypes[j]).equals(paramTypes[j]);
		    }
		    else if (paramTypes[j].isPrimitive()) {
			found = primitiveMap.get(paramTypes[j]).equals(actualTypes[j]);
		    }
		}

		if (!found) {
		    break;
		}
	    }

	    if (found) {
		return m;
	    }
	}

	return null;
    }
}


Example usage:
Method m = ReflectionUtil.getCompatibleMethod(c, "doWork",
	Class.forName("java.lang.String"), 
	Class.forName("java.lang.Integer"),
	Class.forName("java.lang.Boolean")
);
m.invoke(c.newInstance(), "String", new Integer(1), new Boolean(false));
Share |
| Comment  | Tags
1 comment