Suppose I have a unknown interface, and I want to be able to construct an object which, when user calls some method from interface on it, returns something specified by that interface. Eg having a Class class
object, representing unknown Interface
, I want to be able to construct an Object
, which behaves like something which correctly implements that Interface
. For instance, say I'm working on method
public <E> E myMethod(Class<E> class){
...
return res;
}
Where class
is representation of an unknown interface, let for instance
public <E> interface Writer{
public String write(String s);
}
Class<E> class = Writer.class;
All I want now is that any call like
returnedFromMyMethod.write(s);
actually do the job, eg returns given string I know that there's reflection to be used, because all of that is going on in runtime, we don't know what exactly the interface is. But can't figure it out. Any ideas?
EDIT : To avoid misunderstanding.
Writer
as possibly as Runnable
, Comparable
or any other. It is for sure one interface. So question is about creating an object that imitates implementing all methods from given interface
Change your method and interface as
public <E extends Writer> E myMethod(Class<E> clazz) {
...
return res;
}
public interface Writer {
public String write(String s);
}
Now you will be able to call write(String s)
method on the return value of myMethod(Class<E> clazz)
.
Writer w = myMethod(WriterImpl.class);
w.write("any string");
You can put that class into a java decompiler such as javadecompilers.com and then you can find out what interface it extends, or you can go the reflection route like this:
//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();
}
This is what you could do if you wished to use reflection. On the contrary, if I have miss understood what the question was, any Class that implements an Interface automatically has those methods to be called. Therefore, doing class.write(s); would return a String just like normal.
You can create a dynamic proxy :
@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.
As long as you have a plan for how to handle the invocations. Of course there is no way to do that out 'automagically'.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.