I need to call default method of interface (and get the returned value), but the interface is provided by Class object. (There is no other way to pass it then Class in my project)
Here is an example: Let's imagine I have interface:
public interface IExample {
void someOtherAbstractMethod();
default String method() {
return "Test";
}
}
Now imagine I have method
String getReturnValueOfInterfaceMethod(Class<T> clazz, String method_name) throws Exception {
if (!clazz.isInterface()) return null;
Method m = clazz.getMethod(method_name);
if (!m.isDefault()) throw new Exception();
// invoke the method and return the value ("Test")
}
It is for complicated project, this is only an example!!!!
My only idea is to invoke the method using Method#invoke(Object, Object...)
, but I need an instance. So I think I need to create an instance of anonymous class from that interface (Other methods implement as empty or return default values). How do I do that? Or is there any other way to do that without changing the IExample definition.
Thanks!
Because default methods are instance methods by definition, we first need an instance of the interface.
Luckily, java.lang.reflect.Proxy
does exactly that:
var proxy = Proxy.newProxyInstance(IExample.class.getClassLoader(),
new Class<?>[] {IExample.class}, (m, p, a) -> null);
Note that I did pass a very simple invocation handler to the proxy - which will probably yield to errors when the proxy object is used.
This will matter if the default method invokes other methods in the proxy.
Then we can use InvocationHandler.invokeDefault
to call the default method:
Object result = InvocationHandler.invokeDefault(proxy, IExample.class.getMethod("method"));
Again, this will yield to a problem if the default method invokes other methods, including other default methods in the default method body.
If that is required, you need to write a better/more advanced invocation handler.
Also note that InvocationHandler.invokeDefault
was added in Java 16.