我想尝试避免反射调用构造函数,并尝试遵循此帖子中采用的LamdaMetaFactory方法 -
我想要构建的课程如下:
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);
不幸的是,这会返回错误 -
AbstractMethodError:方法 组织/存在/存储/ BrokerFactory $$ LAMBDA $ 55.apply(Ljava /郎/对象; Ljava /郎/对象;)Ljava /郎/对象; 是抽象的。
我尝试修改传递给LambdaMetafactory.metafactory
的各种类型,但我似乎无法做到这一点,并且Javadoc当然不容易理解。
有人可以提出建议吗?
答案 0 :(得分:6)
您犯的错误是您使用的SAM类型。必须使用已擦除类型的apply
方法,因此这将是
methodType(Object.class, Object.class, Object.class)
但你也可以使用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();
// ^^^^^^^^^^^^^^^^^^^