Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java: runtime method resolution

I'm working on some dynamic invocation of code via an interpreter, and I'm getting into the sticky ugly areas of method resolution as discussed in JLS section 15.12.

The "easy" way to choose a method is when you know the exact types of all the arguments, at which point you can use Class.getDeclaredMethod(String name, Class[] parameterTypes). Maybe you have to check method accessibility and the class's superclasses/superinterfaces.

But this doesn't cover any of the following cases, so it's kind of useless:

  • boxing/unboxing primitives
  • subtypes
  • varargs
  • a null argument (which can be any type, unless the interpreter knows otherwise; at compile-time any ambiguity would be eliminating by casting null to a class/interface)
  • primitive type conversion (not part of Java, but allowable in the context of languages -- e.g. Rhino Javascript where all numbers are floating-point, so the Java code might take an int but the caller passes in a number which is either an int or a double)

(see below for a quick example of the first three)

So now I have to write my own method resolution library...

Is there any well-known framework library to assist in this?

package com.example.test.reflect;

import java.lang.reflect.Method;

public class MethodResolutionTest {
    public void compute(int i)              { /* implementation... */ }
    public void compute(Long l)             { /* implementation... */ }
    public void compute(Object obj)         { /* implementation... */ }
    public void compute(String... strings)  { /* implementation... */ }

    public static void main(String[] args) {
        Class<?> cl = MethodResolutionTest.class;

        /* these succeed */
        findAndPrintMethod(cl, "compute", int.class);
        findAndPrintMethod(cl, "compute", Long.class);
        findAndPrintMethod(cl, "compute", Object.class);
        findAndPrintMethod(cl, "compute", String[].class);

        /* these fail */
        findAndPrintMethod(cl, "compute", Integer.class);
        findAndPrintMethod(cl, "compute", long.class);
        findAndPrintMethod(cl, "compute", MethodResolutionTest.class);
        findAndPrintMethod(cl, "compute", String.class, String.class);
    }
    private static void findAndPrintMethod(Class<?> objectClass, 
            String methodName, Class<?>... parameterTypes) 
    {
        try {
            Method method = findMethod(objectClass, methodName, 
                   parameterTypes);
            System.out.println(method.toString());
        }
        catch (SecurityException e) {
            e.printStackTrace();
        }
        catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }
    private static Method findMethod(Class<?> objectClass, 
            String methodName, Class<?>[] parameterTypes) 
        throws SecurityException, NoSuchMethodException 
    {
        return objectClass.getDeclaredMethod(methodName, parameterTypes);
    }
}
like image 556
Jason S Avatar asked May 16 '11 17:05

Jason S


2 Answers

You may want to read this blog post and check out ClassMate. It should do most of the grungy work for you.

like image 154
Holger Hoffstätte Avatar answered Oct 05 '22 00:10

Holger Hoffstätte


Commons beanutils have this function for finding matching methods: getMatchingAccessibleMethod

It works with primitive types but it is somewhat indeterministic as the docs says.

like image 22
jontro Avatar answered Oct 04 '22 23:10

jontro