In the Java project I'm currently working on, I dynamically load classes, and then use the reflection API to find and execute methods on those classes that have specific annotations.
The code that does the actual execution works exclusively from the point of view of the functional interfaces of Java-8 (for compatibility reasons), so I need to have an intermediate step in which Method, detected by reflection, they are converted to the corresponding functional interfaces. I achieve this using the class MethodHandleProxies.
For compatibility reasons, the functional interfaces again considered are common interfaces. This triggers an “unverified conversion” warning when using the method MethodHandleProxies.asInterfaceInstance, as this method returns a bare interface.
The following is a brief example in which the main steps are reproduced:
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandleProxies;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Method;
import java.util.Arrays;
public class TestClass {
private String prefix;
public static void main(String[] args) throws IllegalAccessException, NoSuchMethodException, SecurityException {
Method method = Arrays.stream(TestClass.class.getDeclaredMethods())
.filter(m -> m.isAnnotationPresent(Marker.class))
.findFirst().get();
MethodHandle handle = MethodHandles.lookup().unreflect(method);
MethodInterface<TestClass, String> iface = MethodHandleProxies.asInterfaceInstance(MethodInterface.class, handle);
iface.call(new TestClass("A"), "B");
}
public TestClass(String prefix) {
this.prefix = prefix;
}
@Marker
public void testMethod(String arg) {
System.out.println(prefix + " " + arg);
}
@Retention(RUNTIME)
public @interface Marker { }
@FunctionalInterface
public interface MethodInterface<I,V> {
void call(I instance, V value);
}
}
This code compiles and runs, but has a warning about an unverified conversion on assignment iface.
Creating a MethodInterfacenon-generic would solve this specific problem, but would mean that it would no longer work with method references for arbitrary types (which is desirable for other parts of the code).
For example, with the above definitions TestClass, the MethodInterfacefollowing line compiles:
MethodInterface<TestClass,String> iface = TestClass::testMethod;
MethodInterface :
@FunctionalInterface
public interface MethodInterface {
void call(Object inst, Object value);
}
TestClass::testMethod , .
, :
, ( ), 1. 2 , " ", . , .
, ?