动态的类型语言支持

Java invokedynamic为了动态类型语言支持而进行的改进的,也是JDK8可以顺利实现Loamdba表达式做及时准备

那么什么是动态类型余元

就是对于数据类型的检查的时期不是在编译器而是在执行期间

想Groovt和JavaScirpt等就是动态语言,Java则是标准的静态语言

比如一个类,需要调用一个方法,就好比 obj.println(“hello world”)那么obj的实际类型必然是一个PrintStream的子类,不然哪怕obj是一个确实有println(String)方法的类,但是和接口没有任何继承关系,代码也不能执行

但是在JavaScript中就不一样了,因为在其中

obj在编译期间不确定类型,只有在真正的执行的阶段才会验证,所以只要实现了println()方法就能通过

静态和动态方法的好处各有千秋,在静态方法中,很多编写错误可以在编码的时候就发现,但是动态方法中,可以解决很多静态语言中需要大量臃肿的代码才能实现的功能,更加清晰

在一开始开篇点题的时候,就说了Java现在可以支持其他的语言运行在Java虚拟机之上,目前很多动态语言可以运行在Java虚拟机之上了,但是一直支持的不好,因为Java本身就是一个静态方法,这样会导致编译期间的困难

Java后来新加入了java.lang.invoke包,提供了一种新的动态确定目标方法的机制,称为MethodHandle

在之前,如果想要进行排序,那么可以实现一个带有compare()方法的Comparator接口,然后以这个接口的对象为参数进行排序

不过Method Handle提供了一种新的实现思路.一种新的委托执行的机制

图片

`

通过这种方式,可以做到他那无论调用哪个方法,都可以调用实现的方法

仅仅在Java上看待,MehtodHandle使用和Reflection有着众多的相似之处,但是区别也不少

内部来看,Reflection和MethodHandle机制都是在模拟方法调用,Reflection是模拟Java代码层次的调用

MethodHandler是模拟字节码层次的调用

Refleciton内部包含了方法的签名,描述符以及方法属性表等各种属性的Java端的表示方式,后者仅仅包含和执行该方法的信息,通俗来说,Reflection是重量级,MethodHandle是轻量级

最后总结一下,ReflectionAPI的目标是为了Java语言服务的,而MethodHandle则设计成为可以服务所有Java虚拟机上的语言,其中包含着Java语言

关于字节码中新推出的invokednamic指令

其也是为了帮助虚拟机可以识别其他类型的语言,退出了这种invokednamic指令,可以有效的避免分派的规则固化在虚拟机之中

每一处使用invokedynamic指令的位置都被称为动态调用点,这个指令的第一个参数是CONSTANT_InvokeDynamic_info常量,这个常量中含有

引导方法,方法类型和名称,

引导方法的参数是固定的,且返回值是java.lang.invoke.CallSite对象,根据传入的方法类型和名称获取到一个CallSite对象,最终

invokednamic指令和其他invoke指令最大的区别是分派的逻辑不是由虚拟机决定,而是程序员决定的

一个比较经典的问题就是如何通过子类直接调用祖类中的方法呢,不是调用父类的,下面的代码就解决了这个问题

图片

发表评论

邮箱地址不会被公开。 必填项已用*标注