- java中通过类调用类的方法之前一直使用反射的机制去做,但是jdk1.7中增加了对动态语言的支持,增加了MethodHandle方法
MethodHandle的Demo
新建一个类ClassA,方法println
public class ClassA {
public void println(String s) {
System.out.println(s);
}
}
method handle方法使用
private static MethodHandle getPrintlnMh(Object reveiver) throws NoSuchMethodException, IllegalAccessException {
MethodType methodType = MethodType.methodType(void.class, String.class);
return MethodHandles.lookup().findVirtual(reveiver.getClass(), "println", methodType).bindTo(reveiver);
}
MethodType.methodType()第一个参数是返回类型,第二个以后的参数是方法入参
通过获取MethodType,调用invokeExact方法执行
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, Throwable {
Object obj = new ClassA();
getPrintlnMh(obj).invokeExact("MH ClassA:say hello");
}
- 在java代码中println方法拥有的对象必须是PrintStream的子类(实现了PrintStream接口的类),否则就算是对象确实有println(String)方法,代码依然不能运行,因为类型检查不合法。
MethodHandle调用System.out
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, Throwable {
Object obj = System.out;
getPrintlnMh(obj).invokeExact("MH System.out:say hello");
}
反射调用方法
public static void main(String[] args) {
Class<?> clazz = Class.forName("com.maxbin.invoke.mh.ClassA");
Method method = clazz.getDeclaredMethod("println", String.class);
method.invoke(clazz.newInstance(), "invoke say hello");
}
反射获取的信息比MethodHandle要多。
反射是模拟java代码层面的调用,MethodHandle是模拟字节码层面的调用。