Функциональный интерфейс для передачи любого метода в качестве параметра в Java - PullRequest
0 голосов
/ 17 января 2019

Я пытаюсь написать метод, который принимает 2 параметра - ссылку на класс и ссылку на метод в этом классе. Тип возвращаемого значения самого метода должен быть таким, каким является возвращаемый тип метода этого класса. Например:

public <T> T myMethod (Class<?> c, <reference to a method m in class c>), where m returns something of type <T>.

То есть в моем коде я мог бы вызвать вышеупомянутый метод как:

myMethod (SomeClass.class, x -> x.someMethod(param1, param2))

Обратите внимание, что SomeClass может быть любым классом, а someMethod может быть любым методом в этом классе с любым количеством параметров.

Я вполне уверен, что это возможно при использовании лямбда-кода и функционального интерфейса в Java 8, но не совсем ясно, как его выразить.

Ответы [ 2 ]

0 голосов
/ 17 января 2019

Метод функционального интерфейса должен принимать один аргумент того же типа, что и именованный класс c, поэтому вам нужно определить универсальный тип для этого класса, давайте назовем его C.

Метод функционального интерфейса должен возвращать значение типа T, но позволяет переименовать его R для представления возвращаемого типа.

Это означает, что ваш интерфейс функции может быть: Function<C, R>

Ваше полное объявление метода будет таким:

public <C, R> R myMethod(Class<? extends C> clazz, Function<C, R> method)

Это можно назвать именно так, как вы показали.

Демо

public class Test {
    public static void main(String[] args) throws Exception {
        Test t = new Test();
        String param1 = "Foo", param2 = "Bar";

        String result = t.myMethod(SomeClass.class, x -> x.someMethod(param1, param2));

        System.out.println(result);
    }
    public <C, R> R myMethod(Class<? extends C> clazz, Function<C, R> method) throws Exception {
        C obj = clazz.getConstructor().newInstance();
        return method.apply(obj);
    }
}

class SomeClass {
    public SomeClass() {}
    public String someMethod(String param1, String param2) {
        return param1 + " + " + param2 + ": " + this;
    }
}

выход

Foo + Bar: test.SomeClass@5594a1b5
0 голосов
/ 17 января 2019

То, что вы пытаетесь сделать, не сразу возможно. Это означает, что вы не можете ссылаться на метод, не имея прямого отражающего доступа к нему.

Фактически, myMethod(MyClass.class, myClass -> myClass.Hello) определенно не хорошее решение чего угодно. Подумай, где тебе это понадобится? Если бы метод был статическим, вы могли бы вызвать его в любом случае, а если бы он не был, вам нужен только экземпляр.

Однако вы можете найти свой метод и вызвать его через api отражения:

public Object myMethod(Class<?> clazz) {
    return clazz.getDeclaredMethod("name_of_method", ... /*Any parameters*/).invoke(/*params*/);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...