https://www.zhihu.com/question/21574535/answer/18998914

Java instanceof 关键字是如何实现的?

基本理解

只是在同一个类加载器加载的前提下,使用其生成的对象,去比较才有意义。不同的类加载器加载的类生成对象,互相instanceof返回false。

HotSpot VM具体使用了长度为8的缓存数组,记录某个类从继承深度0到7的超类。HotSpot把类继承深度在7以内的超类叫做“主要超类型”(primary super),把所有其它超类型(接口、数组相关以及超过深度7的超类)叫做“次要超类型”(secondary super)。
对“主要超类型”的子类型判断不需要像Kaffe或JamVM那样沿着super链做遍历,而是直接就能判断子类型关系是否成立。这样,类的继承深度对HotSpot VM做子类型判断的性能影响就变得很小了。
对“次要超类型”,则是让每个类型把自己的“次要超类型”混在一起记录在一个数组里,要检查的时候就线性遍历这个数组。留意到这里把接口类型、数组类型之类的子类型关系都直接记录在同一个数组里了,只要在最初初始化secondary_supers数组时就分情况填好了,而不用像Kaffe、JamVM那样每次做instanceof运算时都分开处理这些情况。

举例来说,如果有下述类继承关系:
Apple <: Fruit <: Plant <: Object
并且以Object为继承深度0,那么对于Apple类来说,它的主要超类型就有:
0: Object
1: Plant
2: Fruit
3: Apple
这个信息就直接记录在Apple类的primary_supers数组里了。Fruit、Plant等类同理。

如果我们有这样的代码:

  1. Object f = new Apple();
  2. boolean result = f instanceof Plant;

也就是变量f实际指向一个Apple实例,而我们要问这个对象是否是Plant的实例。
可以知道f的实际类型是Apple;要测试的Plant类的继承深度是1,拿Apple类里继承深度为1的主要超类型来看是Plant,马上就能得出结论是true。
这样就不需要顺着Apple的继承链遍历过去一个个去看是否跟Plant相等了。

 

字节码

instanceof indexbyte1 indexbyte2
执行时,objectref出栈, indexbyte1 indexbyte2构建一个指向当前类运行时常量池的索引值。 为一个类、接口、数组类型的符号引用
如果objectref为null,那么instanceof指令将int 0推入栈
如果objectref可以转换为这个类,则1入栈,否则0入栈

instanceof解析的更多相关文章

  1. js instanceof 解析

    js中的instanceof运算符 概述 instanceof运算符用来判断一个构造函数的prototype属性所指向的对象是否存在另外一个要检测对象的原型链上 语法 obj instanceofOb ...

  2. JavaScript中instanceof与typeof运算符的用法及区别详细解析

    JavaScript中的instanceof和typeof常被用来判断一个变量是什么类型的(实例),但它们的使用还是有区别的: typeof 运算符 返回一个用来表示表达式的数据类型的字符串. typ ...

  3. instanceof 操作符实现原理解析

    本文会介绍ES6规范中 instanceof 操作符的实现,以及自定义 instanceof 操作符行为的几个方法. 文中涉及的规范相关的代码皆为伪代码,为了便于理解,其中可能会省略一些参数判断逻辑或 ...

  4. 【腾讯Bugly干货分享】WebVR如此近-three.js的WebVR示例解析

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57c7ff1689a6c9121b1adb16 作者:苏晏烨 关于WebVR 最 ...

  5. Android okHttp网络请求之Json解析

    前言: 前面两篇文章介绍了基于okHttp的post.get请求,以及文件的上传下载,今天主要介绍一下如何和Json解析一起使用?如何才能提高开发效率? okHttp相关文章地址: Android o ...

  6. 学习SpringMVC——说说视图解析器

    各位前排的,后排的,都不要走,咱趁热打铁,就这一股劲我们今天来说说spring mvc的视图解析器(不要抢,都有位子~~~) 相信大家在昨天那篇如何获取请求参数篇中都已经领略到了spring mvc注 ...

  7. Spring IoC源码解析——Bean的创建和初始化

    Spring介绍 Spring(http://spring.io/)是一个轻量级的Java 开发框架,同时也是轻量级的IoC和AOP的容器框架,主要是针对JavaBean的生命周期进行管理的轻量级容器 ...

  8. HashMap 源码解析

    HashMap简介: HashMap在日常的开发中应用的非常之广泛,它是基于Hash表,实现了Map接口,以键值对(key-value)形式进行数据存储,HashMap在数据结构上使用的是数组+链表. ...

  9. 【Android自学日记】【转】Android Fragment 真正的完全解析(下)

    上篇博客中已经介绍了Fragment产生原因,以及一些基本的用法和各种API,如果你还不了解,请看:Android Fragment 真正的完全解析(上). 本篇将介绍上篇博客提到的:如何管理Frag ...

随机推荐

  1. Qt编写安防视频监控系统3-通道交换

    一.前言 最开始写通道交换的功能的时候,走了很多弯路,比如最开始用最初级的办法,触发交换的时候,先关闭视频,然后设置新的url重新打开视频,这样处理非常低级而且耗内存还卡还很慢,毕竟重新打开视频都需要 ...

  2. [转]新浪云存储SCS Node.js使用指南

    转载自:https://github.com/SinaCloudStorage/scs-sdk-js scs-sdk-js 新浪云存储(SCS) SDK for Node.js Installatio ...

  3. swift 第十二课 as 的使用方法

    忽略的基础性的问题,应该早点写出这个问题的解释比较好,毕竟 swift 好多的地方都用到了 as as!as?,是非常容易搞晕大脑的 1,as使用场合          (1)从派生类转换为基类,向上 ...

  4. 多个celery如何使用同一个redis做为broker?

    曾经有个哥们提了一个这方面的requests,但是最终没有合入的celery中去,所以目前celery没有这个功能,祥见: https://github.com/celery/kombu/pull/9 ...

  5. CentOS修改主机名称

    centos6 或者centos7修改主机名称的方式 centos6 修改主机名 [root@centos6 ~]$ hostname # 查看当前的hostnmae centos6.com [roo ...

  6. Tomcat 目录结构

    bin目录主要是用来存放tomcat的命令,主要有两大类,一类是以.sh结尾的(linux命令),另一类是以.bat结尾的(windows命令). 很多环境变量的设置都在此处,例如可以设置JDK路径. ...

  7. windows下编译配置libnet-1.2-rc3

    1.下载winpcap(一个底层驱动,可以嗅探.过滤网卡数据包,发包).exe安装包,傻瓜一步式安装 2.下载WpdPack_4_1_2,这个是winpcap的开发者包,解压之后只需要配置相关路径. ...

  8. TF-IDF算法之关键词提取

    (注:本文转载自阮一峰老师的博文,原文地址:http://www.ruanyifeng.com/blog/2013/03/tf-idf.html) 这个标题看上去好像很复杂,其实我要谈的是一个很简单的 ...

  9. poj1222(高斯消元法解异或方程组+开关问题)

    题目链接:https://vjudge.net/problem/POJ-1222 题意:给定一个5×6的01矩阵,改变一个点的状态时它上下左右包括它自己的状态都会翻转,因为翻转2次等价与没有翻转,那么 ...

  10. [CF1010D]Mars Over_位运算性质

    Mars rover 题目链接:http://codeforces.com/problemset/problem/1010/D 数据范围:略. 题解: 因为每次只改一个,改完之后改回去,这个性质很重要 ...