Подражать реализации методов из данного интерфейса во время выполнения - PullRequest
0 голосов
/ 06 мая 2018

Предположим, у меня есть неизвестный интерфейс, и я хочу иметь возможность создать объект, который, когда пользователь вызывает некоторый метод из интерфейса на нем, возвращает что-то, указанное этим интерфейсом. Например. имея объект Class class, представляющий неизвестный Interface, я хочу иметь возможность создать Object, который ведет себя как нечто, что правильно реализует этот Interface. Например, скажем, я работаю над методом

public <E> E myMethod(Class<E> class){
    ...
    return res;
}

Где class - представление неизвестного интерфейса, например,

public <E> interface Writer{
    public String write(String s);
}
Class<E> class = Writer.class;

Все, что я хочу сейчас, - это любой вызов, такой как

returnedFromMyMethod.write(s);

фактически выполняет работу, например, возвращает заданную строку Я знаю, что нужно использовать рефлексию, потому что все это происходит во время выполнения, мы не знаем, что именно представляет собой интерфейс. Но не могу понять это. Есть идеи?

РЕДАКТИРОВАТЬ : во избежание недоразумений.

  1. Это все происходит во время выполнения. Я не знаю, что это за интерфейс. Это может быть Writer, возможно Runnable, Comparable или любой Другой. Это наверняка один интерфейс.
  2. Наш объект не существует, у него нет ни одного из методов, которые мы хотим. Это как строить новый объект (параметризованного типа) с нуля.

Итак, вопрос в том, чтобы создать объект, имитирующий , реализующий все методы из данного интерфейса

Ответы [ 3 ]

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

Вы можете поместить этот класс в Java-декомпилятор, такой как javadecompilers.com, и затем вы можете узнать, какой интерфейс он расширяет, или вы можете пойти по пути отражения следующим образом:

//Assuming the class only extends 1 interface you can do this
Class<?>[] interfaces = class.getClass().getInterfaces();
//Now since we know interfaces[0] is the desired interface, we can get its name
System.out.printLn(intefaces[0].getName()); //You don't have to print the name if you're just going to continue with reflection
//now we're going to define the s variable which will hold what the method returns
String result = "";
//Next using reflection we're going to get the desired method, invoke it, give reflection it's return type and your argument
try {
    result = interfaces([0].getMethod("write").invoke(String.class, args);
    } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException
            | SecurityException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

Это то, что вы можете сделать, если хотите использовать отражение. Напротив, если я не понял, в чем заключался вопрос, любой класс, реализующий интерфейс, автоматически имеет эти методы для вызова. Таким образом, делая class.write (s); вернет String как обычно.

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

Вы можете создать динамический прокси :

@SuppressWarnings("unchecked")
public static <E> E myMethod(Class<E> cls) {
    return (E) Proxy.newProxyInstance(cls.getClassLoader(), new Class[] { cls },
        (Object proxy, Method method, Object[] arguments) -> {
            // handle the invocation of the given method
            return null; // return something actual
        });
}

Writer result = makeProxy(Writer.class); // e.g.

Пока у вас есть план, как обрабатывать вызовы. Конечно, нет никакого способа сделать это «автоматически».

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

Измените свой метод и интерфейс как

public <E extends Writer> E myMethod(Class<E> clazz) {      
    ...
    return res;
}

public interface Writer {
    public String write(String s);
}

Теперь вы сможете вызывать метод write(String s) для возвращаемого значения myMethod(Class<E> clazz).

Writer w = myMethod(WriterImpl.class);
w.write("any string");
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...