Как использовать MethodHandles для вызова метода класса, реализующего интерфейс в Java 8?

public interface Foo {
    int add(int x, int y);
}

public class Bar implements Foo {
    int add(int x, int y) {
        return x+y;
    }
}

Теперь представьте, что у меня есть Foo.class и Bar.class в /usr/local.

Ниже приведен класс, который загружает как Bar, так и Foo и хочет динамически вызывать метод add.

import java.io.File;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.net.URL;
import java.net.URLClassLoader;

public class Test {

    public static void main(String... args) throws Throwable {
        File classFile = new File("/usr/local");
        ClassLoader classLoader = new URLClassLoader(new URL[]{classFile.toURI().toURL()});
        Class fooClass = classLoader.loadClass("Foo");
        MethodHandle mh = MethodHandles
                            .lookup()
                            .findVirtual(fooClass, "add", MethodType.methodType(int.class, int.class, int.class));
        System.out.println((int)mh.invoke(2, 3));
    }
}

Ниже я получаю ошибку

Exception in thread "main" java.lang.invoke.WrongMethodTypeException: cannot convert MethodHandle(Foo,int,int)int to (int,int)int

Вопросов:

  1. Как использовать MethodHandles для вызова метода класса, реализующего интерфейс?
  2. Есть ли способ избежать сумасшедшего кастинга в (int)mh.invoke(2, 3)?
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
0
216
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы забыли указать еще один аргумент - экземпляр, на котором будет вызываться метод:

Class<?> barClass = classLoader.loadClass("Bar");
Object barInstance = barClass.getConstructor().newInstance();
System.out.println(mh.invoke(barInstance, 2, 3));

Кроме того, тип возврата MethodHandle.invoke - Object, поэтому в этом случае вы не можете избежать приведения.

Другие вопросы по теме