Java:运行时方法解析

2022-09-03 16:05:21

我正在通过解释器对代码进行一些动态调用,并且我正在进入方法解析的粘性丑陋领域,如JLS第15.12节中所述。

选择方法的“简单”方法是当您知道所有参数的确切类型时,此时您可以使用Class.getDeclaredMethod(字符串名称,Class[]参数类型)。也许你必须检查方法可访问性和类的超类/超接口。

但这不包括以下任何情况,所以它有点无用:

  • 装箱/取消装箱基元
  • varargs
  • null 参数(可以是任何类型,除非解释器另有说明;在编译时,任何歧义都可以通过向类/接口强制实施 null 来消除)
  • 基元类型转换(不是Java的一部分,但在语言的上下文中是允许的 - 例如Rhino Javascript,其中所有数字都是浮点的,因此Java代码可能采用一个,但调用方传入一个数字,该数字可以是一个或一个intintdouble)

(有关前三个的快速示例,请参见下文)

所以现在我必须编写自己的方法解析库...

是否有任何知名的框架库来协助这项工作?

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);
    }
}

答案 1

您可能想阅读此博客文章并查看ClassMate。它应该为您完成大部分肮脏的工作。


答案 2

Commons beanutils有这个函数来查找匹配的方法:getMatchingAccessibleMethod

它适用于基元类型,但正如文档所说,它有些不确定。