MethodHandles在java的作用就相当于函数指针在C++中的作用,允许java动态引用变量、方法,并调用它们。
1.与C++函数指针的相似
参照一下C++代码
void sort(int list[],const int size,int (*compare)(int,int));
C++中可以传递一个函数指针(入口)作为参数 而Java中却不行,只能实现一个带有compare()方法的接口Comparator 以实现把这个接口作为参数
void sort(List list,Comparator c);
MethodHandle的出现就使java用上了类似于函数指针的方法。
2.MethodHandles的用处(优势)
1.java是静态类型语言,即在编译期就进行类型检查
obj.println("test");
对于这段代码,Java在编译期就会检查obj是否是printStream类型范围,而对于javascript等动态语言则不会检查,它直到运行期间才会进行类型判断,也就是可以根据用户输入或其他运行时因素确定obj的类型
2.MethodHandles使java可以动态引用变量、方法,并调用他们,即在运行期再进行类型检查,并确定调用的对象,而不必在编译期就进行类型检查。
3.案例
public class MethodHandleTest {
static class classA {
public void println(String s) {
System.out.println(s);
}
}
private static MethodHandle getPrintMH(Object reciever) throws Throwable {
//方法的参数类型 返回值类型
MethodType mt = MethodType.methodType(void.class, String.class);
//findVirtual找到Object中的该方法,例如下面的System.out和classA,即找到上述两者的println
//MethodHandles.lookup()是用于创建方法句柄的工厂对象
return MethodHandles.lookup().findVirtual(reciever.getClass(), "println", mt).bindTo(reciever);
//bindTo的作用:调用时,绑定句柄将给定值reciever作为目标的新前导参数插入。
//也就是相当于下面的invokeExact(reciever,"test")
}
public static void main(String[] args) throws Throwable
{
//随机选定一个接收者,这是在运行期间发生的
Object obj=System.currentTimeMillis()%2==0 ? System.out : new classA();
// 传入参数test,将来是被打印出的字段
getPrintMH(obj).invokeExact("test");
}
}
``