12

我目前正在使用一种用 Java 实现的专门的、解释性的编程语言。作为该语言的一小部分,我想添加调用 Java 的功能。在深入探讨反射的所有细节之前,我想知道是否有人知道一个通​​用库,用于执行反射调用 Java 代码的“后端”部分。

也就是说,我将一个字符串(我定义了语法)解析为一些表示 Java 方法调用(或构造函数,或字段访问)的数据结构,然后将该数据结构传递给调用该调用并返回结果的库。特别是,我希望它已经处理了我不想弄清楚的所有边缘情况:

  • 根据参数类型自动选择正确的方法(如智能 Class.getDeclaredMethod())
  • 处理数组和普通对象引用之间的区别
  • ETC

我花了一点时间研究 JVM 上的动态语言的实现,但这些通常比我正在寻找的要复杂得多,或者针对特定语言进行了高度优化。

另一种选择是将我的语法转换为某种动态语言的字符串并用 Rhino 或其他东西调用它,但这比我正在寻找的开销要多一些。

4

11 回答 11

7

试试FEST 反射模块。这是一种进行 Java 反射的流畅方式。例如:

 String name = method("get").withReturnType(String.class)
                         .withParameterTypes(int.class)
                         .in(names)
                         .invoke(8);
于 2008-12-13T21:00:01.503 回答
7

只是对您自己的答案的评论;实际上 beanutils 支持在给定一组参数的情况下获得“近距离匹配”。请参阅getMatchingAccessibleMethod()

BeanUtils 真的很强大,并且有很多用于检查类的实用方法。构造函数自然可以使用相同的支持。

于 2008-12-15T08:52:21.283 回答
4

如果您正在寻找简单性,我创建了一个名为jOOR的简单库,以便于访问 Java 中的反射 API。它支持最基本的操作,而无需构建庞大的 API。这是 jOOR 代码的示例:

String world = 
on("java.lang.String") // Like Class.forName()
.create("Hello World") // Call the most specific matching constructor
.call("substring", 6)  // Call the most specific matching substring() method
.call("toString")      // Call toString()
.get()                 // Get the wrapped object, in this case a String
于 2011-12-29T19:16:02.033 回答
2

看看Java 的脚本支持;我相信它会帮助你解决你的问题。

于 2008-12-13T00:46:15.653 回答
2

看看Apache Commons BeanUtils

于 2008-12-13T19:59:36.507 回答
1

我也会强烈考虑看看 springs ReflectionUtils 类。非常强大的反射处理。

于 2010-01-21T06:10:07.587 回答
1

从死里复活:

invoke(Object object, String methodName, Object[] args) 

Apache Commons lang 正是这种方法。 MethodUtils#invoke

于 2010-06-03T15:56:29.787 回答
1

我已经开始创建一个与hamcrestlambdaj集成的库 com.lexicalscope.fluent-reflection:fluent-reflection

你可以这样写代码;它调用一个类中的所有 post 构造注释方法:

forEach(
   object(subject).methods(annotatedWith(PostConstruct.class)),
   ReflectedMethod.class).call();

博客文章在这里: http: //www.lexicalscope.com/blog/category/software-projects/fluent-reflection/

此处的文档:http: //fluent-reflection.lexicalscope.com/

你可以从这里的 Maven 中心获取它: http ://repo1.maven.org/maven2/com/lexicalscope/fluent-reflection/fluent-reflection/

它目前缺少一些基本功能,例如访问字段,但它适用于方法。可能需要一段时间才能达到一个真正的功能稳定点(比如一两年),因为我只是偶尔工作。但它是按照相当高的质量标准开发的(我希望如此),而且它是开源的,所以如果它具有您需要的所有功能,您基本上可以像现在一样使用它(如果您愿意,您可能只需要稍微调整一下代码)使用已发布的较新版本)。我现在正在一些生产代码中使用它。

它被设计为非常可扩展,因此您可以插入策略以以松散耦合(组合)的方式找到您想要的方法。因此,如果它没有您想要的确切方法查找策略,希望很容易添加它。

于 2011-12-21T11:40:14.297 回答
0

我最终接受了亚历克斯的建议。BeanUtils 对 bean 有很大帮助,但我不想只使用 Beans。FEST 看起来真的很酷,我已将其添加为书签以供进一步研究,但与 BeanUtils 一样,它似乎并不能解决我认为的难题。即,给定方法名称和参数列表,选择最“适合”参数的方法。如果一个方法采用浮点数并且我有一个双精度数,它应该足够聪明,不会因为签名不完全匹配而拒绝该方法。

显然,构建在 JVM 上的脚本语言解决了这个问题,但由于语言特定的优化,其方式比我需要的要复杂得多。因此,由于这是一个次要的实验性特性,我选择了一个使用 Java 1.6 中的脚本引擎支持(尤其是 JavaScript)的快速解决方案。这是基本思想:

private ScriptEngine engine = ... initialize with JavaScript engine ...

private Object invoke(Object object, String methodName, Object[] args) 
   throws RhsFunctionException
{
   // build up "o.method(arg0, arg1, arg2, ...)"
   StringBuilder exp = new StringBuilder("o." + methodName);
   engine.put("o", object);
   buildArgs(arguments, exp);

   try {
      return engine.eval(exp.toString());
   }
   catch (ScriptException e) {
      throw new RhsFunctionException(e.getMessage(), e);
   }
}

private void buildArgs(Object[] args, StringBuilder exp)
{
   // Use bindings to avoid having to escape arguments
   exp.append('(');
   int i = 0;
   for(Symbol arg : args) {
         String argName = "arg" + i;
         engine.put(argName, arg);
         if(i != 0) {
            exp.append(',');
         }
         exp.append(argName);
         ++i;
   }
   exp.append(')');
}

显然还有更多内容,但这是基本思想。我真的不喜欢建立一个字符串并对其进行评估,但是通过使用 Alex 建议的绑定,我避免了大多数转义的陷阱。此外,我有一个干净、简单的接口,如果证明有必要,我可以用“真实”实现替换它。

任何反馈或替代解决方案都非常受欢迎。

于 2008-12-13T21:41:58.017 回答
0

在阅读了这个帖子后,我编写并开源了这段代码,也许你会发现它很有用。

https://github.com/yclian/Reflects.java/blob/master/src/test/java/my/jug/reflects/ReflectsTest.java

它的灵感来自 Guava,因此您可以使用它Predicate来过滤您喜欢的方法。

于 2011-11-07T06:36:39.247 回答
0

反射项目,我相信与上面列出的其他方法相比,它是支持 Java 8 的最新实用反射库,并且最终是截至 2020 年 3 月执行一些高级反射操作的最佳方式。

上面写着:

发布 org.reflections:reflections:0.9.12 - 支持 Java 8
...
Reflections 库每月从 Maven Central 下载超过 250 万次,并被数千个项目和库使用。我们正在寻找维护人员来协助审查拉取请求和管理发布,请联系。
...
Reflections 扫描您的类路径,索引元数据,允许您在运行时查询它,并且可以为项目中的许多模块保存和收集该信息。

与 Java 标准反射结合使用,它应该可以满足您的所有需求。

于 2020-05-11T16:14:38.277 回答