zoukankan      html  css  js  c++  java
  • java关键字之instanceof

    首先来看段测试代码

    1. public class TestInstanceof{
    2. public static void main(String[] args){
    3. int a = 1;
    4. if(a instanceof String){
    5. System.out.println("a instanceof String");
    6. }
    7. }
    8. }
    对这段代码进行编译,编译器首先会将源代码中的字符转换为Token(com.sun.tools.javac.parser.Token) 序列, 我们关注的是关键字instanceof ,它会被映射到一个Token.INSTANCEOF的token.  转换为Token序列这个过程主要是JavacParser结合Scanner类完成。

    接着会尝试生成语法树节点,我们关注的代码 "a instanceof String"会生成JCTree.JCInstanceOf这个节点.

    接下来进行语义分析,主要的过程在com.sun.tools.javac.comp.Attr.attribClassBody这个方法中。在这个方法中,会对上面的JCTree.JCInstanceOf这个节点进行类型检查,见下图


    在第一行的方法中,首先获取变量a所对应的Type,最终发现a是一个int类型的Type,然后进入下面的check



    int类型的Type,其tag为4,所以会进到typeTagError里,tag<9的都是基本类型1--byte,2--char,3--short,4--int,5--long,6--float,7--double,8--boolean,9--void


    可以看到,对于instanceof关键字来说,其左边一定要是个引用类型的变量,所以此处会报错


    ===================================================================================================================================

    接下来我们更改下上面的测试代码

    int a = 1; 改为Integer a = 1;此时的变量a是一个引用了,再次进行编译

    再次进入到visitTypeTest方法中


    前面三个check方法都可以通过,重点看下checkCastable方法,从字面意思来看,这个方法是检查是否可以进行强制转换。查阅jvm的官方文档,是否可以进行强制转换需要遵守以下规范(S instanceof T)


    按照上面的规范,更改后的测试代码也无法编译通过,产生如下报错


    ===================================================================================================================================

    再次更改下上面的测试代码Integer a = 1;改为 String a="1";重新进行编译

    这次上面的check都会通过,最后会为JCTree.JCInstanceOf生成instanceOf字节码指令,这部分代码在com.sun.tools.javac.jvm.Gen.visitTypeTest方法中.最终生成的字节码指令如下:


    if(a instanceof String) 这行代码会生成两条指令,一条instanceof,一条ifeq

    **********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************

    以上的过程都发生在javac编译时,下面看下运行期jvm对该指令是如何进行处理的。首先我们可以自行先思考下,比如 “a instanceof MyClass”,其实可以理解为左边引用a所对应的class是否可以与右边myClass互相进行转换.那再思考下,什么情况下类可以进行相互转换呢?在java中有两种情况,一种是接口实现,另一种是继承,根据这两种情况,即A的super和interface路径上是否存在MyClass,这样就可以很容易实现这个instanceof的功能了,在本人的简易jvm实现中已经实现了这个功能。下面我们来看下hotspot jvm中是如何处理的,Hotspot的实现思路与本人的大致相同,不同的是其思路更为效率点,比如以继承为例子:

    A----->B----->C------>D------>E----->Object

    从左到右为类继承,引用a表示的class A,那如何快速判断a instanceof E为true?在本人的实现中,每个类记录了其父类,所以每次执行该指令时,依次遍历父类,如果有相等则说明为true。而在hotspot vm中,它使用了一个数组来保存这个继承关系,如下:

    A.dis[0]=Object

    A.dis[1]=E

    A.dis[2]=D

    A.dis[3]=C

    A.dis[4]=B

    解释下这个数组,我们定义一个depth,表示继承链上经过多少步可以到达Object,这个多少步就是数组的下标,比如a instanceof E,E只需要经过1步就可到达Object,而在A记录的数组中A.dis[1] = E,正好符合,这样以后判断instanceof时可以O(1)的时间判断出结果!

    实际在hotspot vm中针对instanceof还有其他的优化,具体可以看这篇文章《Fast subtype checking in the HotSpot JVM


    原文地址:https://blog.csdn.net/chengzhang1989/article/details/73309298
  • 相关阅读:
    css
    css加号波浪号
    C++对象池
    C++11 智能指针
    C++内存泄漏检测(调试工具)
    JSONP是个嘛玩意?解决跨域问题?
    使用django + KindEditor 开发个人博客系统
    前端文本框插件KindEditor
    jQuery AJAX
    Django ModelForm表单验证
  • 原文地址:https://www.cnblogs.com/jpfss/p/11382061.html
Copyright © 2011-2022 走看看