Java:运行时方法解析

我正在通过解释器进行一些动态的代码调用,我正在进入JLS第15.12节中讨论的方法解决的粘性丑陋区域。

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

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

  • 装箱/拆箱原语
  • 亚型
  • 可变参数
  • 一个null参数(可以是任何类型,除非解释器另有说明;在编译时,任何歧义都会通过将null转换为类/接口来消除)
  • 原始类型转换(不是Java的一部分,但在语言环境中是允许的 – 例如Rhino Javascript,其中所有数字都是浮点数,因此Java代码可能需要一个int但调用者传入的数字是int或者double

(见下面的前三个快速示例)

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

有没有任何着名的框架库来协助这个?

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

您可能想阅读此博文并查看ClassMate 。 它应该为你做大部分蹩脚的工作。

Commons beanutils具有查找匹配方法的function: getMatchingAccessibleMethod

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

关于番石榴讨论的用户之一建议我查看镜像库 。

不幸的是,它不能处理重载分辨率,至少目前还没有。

我在MVEL和属性方面取得了一些成功,但我不记得它是否可以调度方法调用。

但是,您可能完全在寻找不同的语言。 鉴于问题的本质,我建议看看Groovy,它与Java非常干净地集成。