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

原文地址:https://www.cnblogs.com/jpfss/p/11382061.html

时间: 2024-10-19 05:07:44

java关键字之instanceof的相关文章

Java关键字——instanceof

Java中可以使用instanceof关键字判断一个对象到底是哪一个类的实例 格式:对象 instance 类 返回 boolean类型 通过子类实例化的对象同时是子类和父类的实例,无论是直接声明子类还是声明了父类,然后再通过子类向上转型 如果直接通过父类实例化本类对象,则一定不是子类的实例 //================================================= // File Name : ploy_up_demo //---------------------

Java基础系列--instanceof关键字

原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/8492158.html instanceof关键字是在Java类中实现equals方法最常使用的关键字,表示其左边的对象是否是右边类型的实例,这里右边的类型可以扩展到继承.实现结构中,可以是其真实类型,或者真实类型的超类型.超接口类型等. instanceof左边必须是对象实例或者null类型,否则无法通过编译. instanceof右边必须是左边对象的可转换类型(可强转),否则无法通过编

每日一学--Java关键字instanceof

Java 中的instanceof 运算符是用来在运行时指出对象是否是特定类的一个实例.instanceof通过返回一个布尔值来指出,这个对象是否是这个特定类或者是它的子类的一个实例.

java 关键字与保留字

Java 关键字列表 (依字母排序 共51组),所有的关键字都是小写,在MyEclipse中都会显示不同的颜色: abstract, assert,boolean, break, byte, case, catch, char, class, const, continue, default, do, double, else, enum,extends, final, finally, float, for, if, implements, import, instanceof, int, i

java中的instanceof

instanceof是Java.php的一个二元操作符(运算符),和==,>,<是同一类东西.由于它是由字母组成的,所以也是Java的保留关键字.它的作用是判断其左边对象是否为其右边类的实例,返回boolean类型的数据.可以用来判断继承中的子类的实例是否为父类的实现.相当于c#中的is操作符.java中的instanceof运算符是用来在运行时指出对象是否是特定类的一个实例.instanceof通过返回一个布尔值来指出,这个对象是否是这个特定类或者是它的子类的一个实例. instanceof

Java关键字

Java的关键字[个人整理] 关键字总览:-----------abstract.assert.boolean.break.byte.case.catch.char.class.continue.default.do.double.else.enum.extends.final.finally.float.for.if.implements.import.instanceof.int.interface.long.native.new.package.private.protected.publ

java 中的instanceof的用法

instanceof 运算符是Java.php的一个二元操作符(运算符),和==.>.<是同一类东西.由于它是由字母组成的,所以也是Java的保留关键字.它的作用是判断其左边对象是否为其右边类的实例,返回boolean类型的数据.可以用来判断继承中的子类的实例是否为父类的实现.相当于c#中的is操作符.java中的instanceof运算符是用来在运行时指出对象是否是特定类的一个实例.instanceof通过返回一个布尔值来指出.  用法:result = object instanceof

再回首,Java温故知新(二):Java关键字

Java中类型和方法名的定义规则很宽松,但也不是可以随意定义,基本的规则为必须是英文字母开头且不能使用Java关键字,这里摘录下书中的附录,具体到每个关键字的用法会在后续的学习中陆续进行实践. 关键字 说明 abstract 标识抽象类或抽象方法 assert 查找内部程序错误 boolean 布尔类型变量 break 跳出switch语句或者循环语句 byte 8位整数类型 case switch开关语句的分支 catch try...catch语句中异常处理部分 char Unicode字符

java学习笔记3——java关键字

java学习笔记3——java关键字 虽然老师说不用刻意的去记忆,但是我还是在网上找到了非常详细的注解,再次收藏 关键字的类型表: 各个关键字的详细注解和实例,按首字母排序: 1.abstract abstract 关键字可以修改类或方法. abstract 类可以扩展(增加子类),但不能直接实例化. abstract 方法不在声明它的类中实现,但必须在某个子类中重写. -示例- public abstract class MyClass{ } public abstract String my