novedades metodo java reflection interface java-8

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 } }