【发布时间】:2019-03-19 01:08:44
【问题描述】:
我正在尝试使用 Java 的 LambdaMetaFactory 来动态实现通用 lambda,Handler<RoutingContext>:
public class RoutingContext {
// ...
}
@FunctionalInterface
public interface Handler<X> {
public void handle(X arg);
}
public class HomeHandler extends Handler<RoutingContext> {
@Override
public void handle(RoutingContext ctx) {
// ...
}
}
这是我在LambdaMetaFactory 的尝试:
try {
Class<?> homeHandlerClass = HomeHandler.class;
Method method = homeHandlerClass.getDeclaredMethod(
"handle", RoutingContext.class);
Lookup lookup = MethodHandles.lookup();
MethodHandle mh = lookup.unreflect(method);
MethodType factoryMethodType = MethodType.methodType(Handler.class);
MethodType functionMethodType = mh.type();
MethodHandle implementationMethodHandle = mh;
Handler<RoutingContext> lambda =
(Handler<RoutingContext>) LambdaMetafactory.metafactory(
lookup,
"handle",
factoryMethodType,
functionMethodType,
implementationMethodHandle,
implementationMethodHandle.type())
.getTarget()
.invokeExact();
lambda.handle(ctx);
} catch (Throwable e) {
e.printStackTrace();
}
这给出了错误:
java.lang.AbstractMethodError: Receiver class [...]$$Lambda$82/0x00000008001fa840
does not define or inherit an implementation of the resolved method abstract
handle(Ljava/lang/Object;)V of interface io.vertx.core.Handler.
我已经为functionMethodType 和implementationMethodHandle 尝试了一系列其他选项,但还没有成功。此外,即使我将 RoutingContext.class 引用替换为 Object.class,这也无法修复错误。
让lambda.handle(ctx) 调用成功的唯一方法是更改HomeHandler,使其不扩展Handler,使HomeHandler::handle 静态,并将RoutingContext.class 更改为Object.class。奇怪的是,我仍然可以将生成的 lambda 转换为 Handler<RoutingContext>,即使它不再扩展 Handler。
我的问题:
如何让
LambdaMetaFactory使用非静态方法?对于这个非静态 SAM 类
HomeHandler,它如何在后台处理实例分配?LambdaMetaFactory是否创建接口实现的单个实例,不管有多少方法调用,因为在这个例子中没有捕获的变量?或者它是否为每个方法调用创建一个新实例?还是我应该创建一个实例并以某种方式将其传递给 API?如何让
LambdaMetaFactory使用泛型方法?
编辑:除了下面的精彩答案之外,我还看到这篇博客文章解释了所涉及的机制:
https://medium.freecodecamp.org/a-faster-alternative-to-java-reflection-db6b1e48c33e
【问题讨论】:
-
@Holger 你好像回答了很多相关的问题,你大概知道答案了:-)
-
很遗憾,@Username 不适用于尚未涉及目标用户的帖子。
标签: java lambda java-9 methodhandle lambda-metafactory