Как вызвать конструктор, используя LambdaMetaFactory? - PullRequest
0 голосов
/ 07 мая 2018

Я хочу попытаться избежать рефлексии для вызова конструктора, и я пытаюсь следовать подходу LamdaMetaFactory, принятому в этом посте - Более быстрые альтернативы рефлексии Java

Мой класс, который я хочу построить, выглядит так:

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 $$ Лямбда $ 55.apply (Ljava / языки / объект; Ljava / языки / объект;) Ljava / языки / объект; абстрактно.

Я попытался изменить различные типы, переданные в LambdaMetafactory.metafactory, но я не могу понять, как это правильно, и Javadoc, конечно, не так легко понять.

Может кто-нибудь посоветовать, пожалуйста?

1 Ответ

0 голосов
/ 07 мая 2018

Ошибка, которую вы сделали, в типе 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();
//              ^^^^^^^^^^^^^^^^^^^
...