如何调用一个对象的方法?我们可以通过实例化对象直接调用、使用反射机制、通过代理对象等,本文介绍一种新的方法MethodHandle,这种方法在开发中很少会用到,但使用起来感觉很顺手。
什么是MethodHandle?
MethodHandle是JDK1.7实现了JSR-292,新加入的java.lang.invoke
包中的一个重要组成部分,这个包的主要是在单纯通过符号引用来确定调用的目标方法以外,提供一种析的动态确定目标方法的机制。
示例
1 | package com.bk.exercise; |
运行结果如下显示
1 | I'm sing Summer train |
从示例可以看出来,使用MethodHandle并没有什么困难,可以实现方法的调用,可是很多人会问,反射不也可以做相同的事情么,我们经常会使用反射,而不会使用这种方法。
MethodHandle与Reflection的区别
如果站在Java语言的角度来看,他们确实是有很多相似之处,但是从他们其它角度来看,确有很大的区别
- 从本质上来讲,
Reflection
和MethodHandle
机构都是在模拟方法调用,但Reflection是模拟的Java代码层面的方法调用,而MethodHandle是在模拟字节码层面的方法调用。 Reflection
中的Method是重量级的,MethodHandle
对象是轻量级的,Reflection中包含了方法的签名、描述符以及方法属性表中各种属性、执行权限等,而MethodHandle
仅仅包含与执行该方法相关的信息MethodHandle
是字符码的方法指令调用模拟,理论上可以模拟出和JVM上一样的优化如方法内联,但是Reflection
去调用方法则不可以Reflection API
的设计目标是为Java语言服务
的,而MethodHandle
设计成可服务于所有Java虚拟机之上
的语言
写在最后
MethodHandles.lookup中的findStatic()
、findVirtual()
、findSpecia()
三个谅正是为了对应invokestatic
、invokevirtual&invokeinterface
、invokespecial这几条字节码指令的执行权限校验行为,本文中只讲到了findVirtual()方法,其它两个方法读者可以自行尝试一下。
java.lang.invoke
包中的内容可以看一看,别有一番有洞天