如何使用 LambdaMetaFactory 调用构造函数?
How to invoke constructor using LambdaMetaFactory?
我想尝试避免调用构造函数的反射,并尝试遵循此 post - Faster alternatives to Java's reflection
中采用的 LamdaMetaFactory 方法
我要构造的 class 看起来像:
interface DBBroker {}
public class NativeBroker implements DBBroker {
public NativeBroker(BrokerPool brokerPool, final Configuration configuration) {
}
}
使用 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);
不幸的是这个 returns 错误 -
AbstractMethodError: Method
org/exist/storage/BrokerFactory$$Lambda.apply(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
is abstract.
我已经尝试修改传递给 LambdaMetafactory.metafactory
的各种类型,但我似乎不太正确,而且 Javadoc 肯定不容易理解。
有人可以指点一下吗?
你犯的错误是你使用的SAM类型。 apply
方法的擦除类型必须用于此,因此将是
methodType(Object.class, Object.class, Object.class)
但您也可以使用 mh.type().generic()
和 returns 相同的东西:
BiFunction<BrokerPool, Configuration, DBBroker> constructor =
(BiFunction<BrokerPool, Configuration, DBBroker>)
LambdaMetafactory.metafactory(
lookup, "apply", methodType(BiFunction.class),
mh.type().generic(), mh, mh.type()).getTarget().invokeExact();
// ^^^^^^^^^^^^^^^^^^^
我想尝试避免调用构造函数的反射,并尝试遵循此 post - Faster alternatives to Java's reflection
中采用的 LamdaMetaFactory 方法我要构造的 class 看起来像:
interface DBBroker {}
public class NativeBroker implements DBBroker {
public NativeBroker(BrokerPool brokerPool, final Configuration configuration) {
}
}
使用 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);
不幸的是这个 returns 错误 -
AbstractMethodError: Method org/exist/storage/BrokerFactory$$Lambda.apply(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; is abstract.
我已经尝试修改传递给 LambdaMetafactory.metafactory
的各种类型,但我似乎不太正确,而且 Javadoc 肯定不容易理解。
有人可以指点一下吗?
你犯的错误是你使用的SAM类型。 apply
方法的擦除类型必须用于此,因此将是
methodType(Object.class, Object.class, Object.class)
但您也可以使用 mh.type().generic()
和 returns 相同的东西:
BiFunction<BrokerPool, Configuration, DBBroker> constructor =
(BiFunction<BrokerPool, Configuration, DBBroker>)
LambdaMetafactory.metafactory(
lookup, "apply", methodType(BiFunction.class),
mh.type().generic(), mh, mh.type()).getTarget().invokeExact();
// ^^^^^^^^^^^^^^^^^^^