Java反射传递方法作为另一种方法的参数?

时间:2016-09-29 03:00:49

标签: java reflection java-8

我可以获得一个注释没有问题的方法列表......

Method[] m = clazz.getDeclaredMethods();

现在我想将方法​​[x]传递给一个函数。例如......

router.get("/").handler(RoutingContext handler)

我想将它作为方法引用传递给处理程序。

在java 8中,我们可以router.get("/").handler(this::myMethod)

更新示例:

public void myFunction() throws Exception {

    Router routes = Router.router(...);

    Handler<RoutingContext> handler = this::myHandler;
    routes.route("/").handler(handler);
    routes.route("/someOtherRoute").handler(this::anotherHandler);

}

public void myHandler(final RoutingContext rcs) {
    rcs.doSomething();
}

我想注释函数myHandler,以便我可以反思地找到它并将其添加到“路由器”中。因此,通过反射,我可以得到一个已注释没有问题的方法列表,然后为每个方法添加到我的路由器...

所以说我有一些“网络”anotations ......

@GET
public void myHandler(final RoutingContext rcs) {
    rcs.doSomething();
}

@POST
public void anotherHandler(final RoutingContext rcs) {
    rcs.doSomething();
}

我可以使用反射列出这些方法。酷没问题。但是我希望将它们作为方法引用传递给router.handler(),如上例所示......

如果你没有猜到它是一个网络框架,不,我不会发布到野外不像我们需要另一个。这是出于学习目的lol。

更新

路由器的类型为:https://github.com/vert-x3/vertx-web/blob/master/vertx-web/src/main/java/io/vertx/ext/web/Router.java

而且hander是vertx.io的一部分

2 个答案:

答案 0 :(得分:2)

您可以简单地传递执行反射调用的lambda表达式,例如

{user => {project => { } }

完成这项工作。

或者,您确实可以生成一个等效于方法引用的实例,这需要更深入的了解反射操作(以及您未发布的routes.route("/").handler(rc -> { try { method.invoke(this, rc); } catch (ReflectiveOperationException ex) { throw new RuntimeException(ex);} } ); 接口)。例如。生成一个Handler来调用您可以使用的Consumer<RoutingContext>

method

要生成MethodHandles.Lookup l=MethodHandles.lookup(); Consumer<RoutingContext> c=(Consumer<RoutingContext>) LambdaMetafactory.metafactory(l, "accept", MethodType.methodType(Consumer.class, getClass()), MethodType.methodType(void.class, Object.class), l.unreflect(method), MethodType.methodType(void.class, RoutingContext.class)) .getTarget().invoke(this); ,您必须将HandlerConsumerHandler的匹配项替换为"accept"的功能方法的名称。此外,如果Handler的类型参数的下限不是Handler,则必须将Object替换为下限的原始类型。

documentation of LambdaMetaFactory非常详尽,related Q&A’s on SO提供了更多信息,但是,如果您有任何疑问,只需坚持反思性调用......

答案 1 :(得分:0)

使用方法引用时,引用的类型是实现接口类型的类(特别是功能接口)。在您的情况下,方法引用的类型似乎是Handler<RoutingContext>

您似乎正在寻找一种方法将Method转换为您选择的功能界面。我不知道直接的方法,但你可以尝试像

这样的东西
public class HandlerFromMethod implements Handler<RoutingContext> {

    final private Method method;

    public HandlerFromMethod(Method m) {
        method = m; 
    }

    @Override
    public void apply(final RoutingContext rcs) {
        method.invoke(null, rcs);
    }
}

现在,如果您有Method m,new HandlerFromMethod(m)会创建一个可用作Handler<RoutingMethod>的对象,并在调用时调用m

如果方法是实例方法,那么您将要向构造函数添加另一个参数以指定它将对其进行操作的实例,并将其用作invoke的第一个参数。

我假设Handler中的方法名为apply;如果它是其他内容,则更改上述代码中的名称。

免责声明:我还没有对此进行测试。