novedades - metodo default java
¿Cómo invoco los métodos predeterminados de Java 8 de forma reflexiva? (3)
Dada esta simple interfaz de "Hola Mundo" ish Java 8, ¿cómo invoco su método hello () a través de la reflexión?
public interface Hello {
default String hello() {
return "Hello";
}
}
He encontrado una solución para crear instancias a partir de interfaces como la anterior mediante el uso reflexivo del código de sun.misc.ProxyGenerator
que define una clase HelloImpl
mediante el ensamblaje de bytecode. Ahora puedo escribir:
Class<?> clazz = Class.forName("Hello");
Object instance;
if (clazz.isInterface()) {
instance = new InterfaceInstance(clazz).defineClass().newInstance();
} else {
instance = clazz.newInstance();
}
return clazz.getMethod("hello").invoke(instance);
... pero eso es bastante feo.
No puede llamarlo directamente, ya que necesita una instancia de una clase implementadora. Y para eso, necesitas una clase implementadora. default
método default
no es un método static
, y tampoco puede crear una instancia de una interfaz.
Entonces, supongamos que tiene una clase implementadora:
class HelloImpl implements Hello { }
Puede invocar el método de esta manera:
Class<HelloImpl> clazz = HelloImpl.class;
Method method = clazz.getMethod("hello");
System.out.println(method.invoke(new HelloImpl())); // Prints "Hello"
Puede usar MethodHandles para eso:
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ReflectiveDefaultMethodCallExample {
static interface Hello {
default String hello() {
return "Hello";
}
}
public static void main(String[] args) throws Throwable{
Hello target =
//new Hello(){};
(Hello)Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),new Class[]{Hello.class}, (Object proxy, Method method, Object[] arguments) -> null);
Method method = Hello.class.getMethod("hello");
Object result = MethodHandles.lookup()
.in(method.getDeclaringClass())
.unreflectSpecial(method,method.getDeclaringClass())
.bindTo(target)
.invokeWithArguments();
System.out.println(result); //Hello
}
}