深入JVM MethodHandle

——动态语言类型

动态类型语言的关键特征是它的类型检查主体过程发生在运行期而不是编译期,如: python javascript PHP等,相对的,编译期需要进行类型检查的语言有C++ Java

——obj.println("test");

对于这段代码,静态类型语言如Java编译期就会检查obj是否是printStream类型范围,而对于javascript语言则不会检查,它直到运行期间才会进行类型判断

一门语言的检查行为要在运行期发生 和在编译期就发生没有必然逻辑关系,而取决于语言规范中的实现和人为定义,静态语言的方法的符号引用在编译时产生,而动态语言的方法只有在运行期间才能确定接收者类型

——java.lang.invoke包

这个包的主要目的是在之前单纯依靠符号引用确定调用方法确定目标方法方式之外,提供一种新的动态确定目标方法的机制,称为MethodHandle . 这种方式与C++中的函数指针十分相似。以简单的排序方法为例

——void sort(int list[],const int size,int (*compare)(int,int))

C++中可以传递一个函数指针(入口)作为参数   而Java中却不行,只能实现一个带有compare()方法的接口Comparator 以实现把这个接口作为参数

——void sort(List list,Comparator c)

不过在拥有MethodHandle之后,Java语言也可以用于类似于函数指针的方法

案例演示:

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);
		//方法的参数类型 返回值类型
		return MethodHandles.lookup().findVirtual(reciever.getClass(),"println",mt).bindTo(reciever);
		//找到Object中的该方法
		
		
	}

	public static void main(String[] args) throws Throwable{
		Object obj=System.currentTimeMillis()%2==0 ? System.out : new classA();//随机选定一个接收者
		getPrintMH(obj).invokeExact("test");

	}

}

其中ClassA 类对象 和 System.out对象都有println方法 而具体调用哪个方法可以通过实际运行随机确定

MethodHandle对象 相当于对方法的描述,可以理解为实际调用方法的引用

——void sort(List list ,MethodHandle compare)

进一步讲,MethodHandle似乎和Java反射相似,但是2者还是有不同之处

  • 从本质上讲,Reflection和MethodHandle机制都是在模拟方法调用,但Reflection是模拟Java代码层次的方法调用,而MethodHandle是在模拟字节码层次的方法调用
  • Reflection包含很多方法的信息,是重量级的,而MethodHandle是轻量级的

最关键的区别,仅仅站在Java语言的角度,Reflection API只是为Java语言使用,而MethodHandle则设计成可服务于所有Java虚拟机之上的语言,也包括Java语言

猜你喜欢

转载自blog.csdn.net/qq_33369979/article/details/88067580