MethodFinder.java

Power Java
Limitations of reflective method lookup
by Paul Holser
Listing 4. MethodFinder.java.


package reflection;

import java.util.Vector;
import java.util.Hashtable;
import java.lang.reflect.Method;

public class MethodFinder {
  Class c;
  Hashtable methodHash = new Hashtable();
  Hashtable paramHash = new Hashtable();

  public MethodFinder(Class c) {
    this.c = c;

    Method[] methods = c.getMethods();

    for (int i = 0; i < methods.length; i++) {
      String methodName = methods[i].getName();
      Vector v = (Vector) methodHash.get(methodName);

      if (v == null) {
        v = new Vector();
        methodHash.put(methodName, v);
      }

      v.addElement(methods[i]);
      Class[] paramTypes = methods[i].getParameterTypes();
      paramHash.put(methods[i], paramTypes);
    }
  }

  public Method findMethod(String methodName, Object[] params)
  throws NoSuchMethodException {
    Vector v = (Vector) methodHash.get(methodName);

    if (v == null)
      throw new NoSuchMethodException(methodName);
 
    for (int i = 0; i < v.size(); i++) {
      Method m = (Method) v.elementAt(i);
      boolean ok = true;
      Class[] paramTypes = (Class[]) paramHash.get(m);

      if (params == null)
        params = new Object[0];

      if (paramTypes.length != params.length)
        continue;

      for (int j = 0; j < paramTypes.length; j++) {
        if (params[j] == null)
          continue;

        Class c = params[j].getClass();
        Class paramClass = paramTypes[j];

        if (paramClass.isPrimitive()) {
          if (paramClass.equals(Integer.TYPE)) {
            if (c.equals(Integer.class))
              continue;
            else {
              ok = false;
              break;
            }
          }
          else if (paramClass.equals(Double.TYPE)) {
            if (c.equals(Double.class))
              continue;
            else {
              ok = false;
              break;
            }
          }
          else if (paramClass.equals(Boolean.TYPE)) {
            if (c.equals(Boolean.class))
              continue;
            else {
              ok = false;
              break;
            }
          }
          else if (paramClass.equals(Long.TYPE)) {
            if (c.equals(Long.class))
              continue;
            else {
              ok = false;
              break;
            }
          }
          else if (paramClass.equals(Character.TYPE)) {
            if (c.equals(Character.class))
              continue;
            else {
              ok = false;
              break;
            }
          }
          else if (paramClass.equals(Byte.TYPE)) {
            if (c.equals(Byte.class))
              continue;
            else {
              ok = false;
              break;
            }
          }
          else if (paramClass.equals(Float.TYPE)) {
            if (c.equals(Float.class))
              continue;
            else {
              ok = false;
              break;
            }
          }
          else if (paramClass.equals(Short.TYPE)) {
            if (c.equals(Short.class))
              continue;
            else {
              ok = false;
              break;
            }
          }

          break;
        }
        else {
          if (! paramClass.isAssignableFrom(c)) {
            ok = false;
            break;    // not right method
          }
        }
      }

      if (ok)
        // if we get here, must have found right method
        return m;
    }

    throw new NoSuchMethodException(methodName);
  }
}

About the Author

Paul Holser is a senior consultant at Valtech, an international consulting group specializing in e-business technologies. He can be contacted at [email protected].