gpt4 book ai didi

java - 具有泛型类型具体实现的 LambdaMetaFactory

转载 作者:塔克拉玛干 更新时间:2023-11-03 04:54:37 26 4
gpt4 key购买 nike

我正在尝试使用 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.classObject.class .奇怪的是我仍然可以将生成的 lambda 转换为 Handler<RoutingContext> ,即使它不再扩展 Handler .

我的问题:

  1. 我如何获得 LambdaMetaFactory使用非静态方法?

  2. 对于这个非静态 SAM 类 HomeHandler ,这如何与引擎盖下的实例分配一起工作?是否LambdaMetaFactory创建接口(interface)实现的单个实例,无论有多少方法调用,因为在这个例子中没有捕获变量?或者它是否为每个方法调用创建一个新实例?还是我应该创建一个实例并以某种方式将其传递给 API?

  3. 我如何获得 LambdaMetaFactory使用泛型方法?

编辑:除了下面的好答案之外,我还看到了这篇解释所涉及机制的博文:

https://medium.freecodecamp.org/a-faster-alternative-to-java-reflection-db6b1e48c33e

最佳答案

Or was I supposed to create a single instance and pass it in to the API somehow?

是的。 HomeHandler::handle 是一个实例方法,这意味着您需要一个实例来创建功能接口(interface)包装器,或者每次调用它时都传递一个实例(为此 Handler 获胜'不能作为 FunctionalInterface 类型工作)。

要使用捕获的实例,您应该:

  • 更改 factoryMethodType 也采用 HomeHandler 实例
  • functionMethodType 更改为 SAM 的删除类型,它以 Object 作为参数。
  • instantiatedMethodType 参数更改为没有捕获的 HomeHandler 实例的目标方法句柄的类型(因为它已被捕获,您不再需要它作为参数) .
  • 在创建功能接口(interface)接口(interface)时将 HomeHandler 的实例传递给 invokeExact

-

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, HomeHandler.class);
MethodType functionMethodType = MethodType.methodType(void.class, Object.class);
MethodHandle implementationMethodHandle = mh;

Handler<RoutingContext> lambda =
(Handler<RoutingContext>) LambdaMetafactory.metafactory(
lookup,
"handle",
factoryMethodType,
functionMethodType,
implementationMethodHandle,
implementationMethodHandle.type().dropParameterTypes(0, 1))
.getTarget()
.invokeExact(new HomeHandler()); // capturing instance
lambda.handle(ctx);

当然,由于HomeHandler实现了Handler,您可以直接使用捕获的实例;

new HomeHandler().handle(ctx);

或者利用编译器生成元工厂代码,它也使用invokedynamic,意味着LambdaMetafactory.metafactory返回的CallSite只会创建一次:

Handler<RoutingContext> lambda = new HomeHandler()::handle;
lambda.handle(ctx);

或者,如果功能接口(interface)类型是静态知道的:

MethodHandle theHandle = ...
Object theInstance = ...
MethodHandle adapted = theHandle.bindTo(theInstance);
Handler<RoutingContext> lambda = ctxt -> {
try {
adapted.invokeExact(ctxt);
} catch (Throwable e) {
throw new RuntimeException(e);
}
};
lambda.handle(new RoutingContext());

关于java - 具有泛型类型具体实现的 LambdaMetaFactory,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52802611/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com