如何使用LambdaMetaFactory调用构造函数?

ada*_*ter 9 java lambda invokedynamic java-8

我想尝试避免反射调用构造函数,并尝试遵循本文中采用的LamdaMetaFactory方法 - 更快地替代Java的反射

我想要构建的类看起来像:

interface DBBroker {}

public class NativeBroker implements DBBroker {
    public NativeBroker(BrokerPool brokerPool, final Configuration configuration) {
    }
}
Run Code Online (Sandbox Code Playgroud)

使用LambaMetaFactory我试图构造一个BiFunction<BrokerPool, Configuration, DBBroker>替换直接调用构造函数.

到目前为止我的代码看起来像:

Class<? extends DBBroker> clazz =
    (Class<? extends DBBroker>) Class.forName("org.exist.storage.NativeBroker");

MethodHandles.Lookup lookup = MethodHandles.lookup();
MethodHandle mh =
    lookup.findConstructor(clazz, MethodType.methodType(void.class, new Class[] {BrokerPool.class, Configuration.class}));

BiFunction<BrokerPool, Configuration, DBBroker> constructor 
    (BiFunction<BrokerPool, Configuration, DBBroker>)
        LambdaMetafactory.metafactory(
                    lookup, "apply", MethodType.methodType(BiFunction.class),
                    mh.type(), mh, mh.type()).getTarget().invokeExact();

final DBBroker broker = constructor.apply(database, conf);
Run Code Online (Sandbox Code Playgroud)

不幸的是,这会返回错误 -

AbstractMethodError:方法org/exists/storage/BrokerFactory $$ Lambda $ 55.apply(Ljava/lang/Object; Ljava/lang/Object;)Ljava/lang/Object; 是抽象的.

我已经尝试修改传递给LambdaMetafactory.metafactory它的各种类型,但我似乎无法做到这一点,并且Javadoc当然不容易理解.

有人可以提出建议吗?

Jor*_*nee 6

您犯的错误是您使用的SAM类型.必须使用擦除类型的apply方法,这样就可以了

methodType(Object.class, Object.class, Object.class)
Run Code Online (Sandbox Code Playgroud)

但你也可以使用mh.type().generic()哪个返回相同的东西:

BiFunction<BrokerPool, Configuration, DBBroker> constructor =
(BiFunction<BrokerPool, Configuration, DBBroker>)
    LambdaMetafactory.metafactory(
                lookup, "apply", methodType(BiFunction.class),
                mh.type().generic(), mh, mh.type()).getTarget().invokeExact();
//              ^^^^^^^^^^^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)

  • 通常,`LambdaMetafactory`生成的类比`MethodHandleProxies`提供的代理更有效,所以这不是你是否需要'LambdaMetafactory`的问题...... (3认同)
  • 对于大多数情况,`erase()`更接近于'generic()`的意图. (2认同)