Java里面instanceof怎么实现的

开始彻底一头雾水呀,后面看了Java指令集的介绍,逐渐理解了。html

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

 

下面这个答案比较直白面试

你在面月薪10000的Java高级研发职位。面试官对JVM有一些了解,想让你说说JVM会如何实现 instanceof 指令。
但他可能也没看过实际的JVM是怎么作的,只是臆想过一下而已。JVM的规定就是“底层”。这种状况就给他JVM规范对 instanceof 指令的定义就好: Chapter 6. The Java Virtual Machine Instruction Set, JVM规范Java SE 7版 根据规范来臆想一下实现就能八九不离十的混过这题了。 地址: http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html#jvms-6.5.instanceof

 

上面指令的定义详细解释以下(解释和重要点已经飘红指出):oracle

instanceof

Operation

Determine if object is of given typejvm

Format


instanceof
indexbyte1
indexbyte2
oop

Forms

instanceof = 193 (0xc1)性能

Operand Stack

..., objectref →spa

..., resultcode

Description

The objectref, which must be of type reference, is popped from the operand stack. The unsigned indexbyte1 and indexbyte2 are used to construct an index into the run-time constant pool of the current class (§2.6), where the value of the index is (indexbyte1 << 8) | indexbyte2. The run-time constant pool item at the index must be a symbolic reference to a class, array, or interface type.component

 

If objectref is null, the instanceof instruction pushes an int result of 0 as an int on the operand stack.

意思是左侧是null,就返回false.(另外,右侧不能为null)

 

Otherwise, the named class, array, or interface type is resolved (§5.4.3.1). If objectref is an instance of the resolved class or array or implements the resolved interface, the instanceof instruction pushes an int result of 1 as an int on the operand stack; otherwise, it pushes an int result of 0.

这个只是概述,下面是详细解释。分为多钟状况。

The following rules are used to determine whether an objectref that is not null is an instance of the resolved type: If S is the class of the object referred to by objectref and T is the resolved class, array, or interface type, instanceof determines whether objectref is an instance of T as follows:

  • If S is an ordinary (nonarray) class, then:

    • If T is a class type, then S must be the same class as T, or S must be a subclass of T;

    • If T is an interface type, then S must implement interface T.

  • If S is an interface type, then:

    • If T is a class type, then must be Object.

    • If T is an interface type, then T must be the same interface as S or a superinterface of S.

  • If S is a class representing the array type SC[], that is, an array of components of type SC, then:

    • If T is a class type, then must be Object.

    • If T is an interface type, then T must be one of the interfaces implemented by arrays (JLS §4.10.3).

    • If T is an array type TC[], that is, an array of components of type TC, then one of the following must be true:

      • TC and SC are the same primitive type.

      • TC and SC are reference types, and type SC can be cast to TC by these run-time rules.

 

Linking Exceptions

During resolution of the symbolic reference to the class, array, or interface type, any of the exceptions documented in §5.4.3.1 can be thrown.

Notes

The instanceof instruction is very similar to the checkcast instruction (§checkcast). It differs in its treatment of null(上面提到,左侧null会直接返回false), its behavior when its test fails (checkcast throws an exception, instanceof pushes a result code), and its effect on the operand stack.

 

下面这个答案比较“晦涩”

你在面试月薪10000以上的Java资深研发职位,注重性能调优啥的。这种职位虽然不直接涉及JVM的研发,但因为性能问题常常源自“抽象泄漏”,
对实际使用的JVM的实现的思路须要有所了解。面试官对JVM的了解可能也就在此程度。
对付这个能够用一篇论文:Fast subtype checking in the HotSpot JVM。
以前有个讨论帖里讨论过对这篇论文的解读:请教一个share/vm/oops下的代码作fast subtype check的问题

其中提到了 “抽象泄露”,后面会单开文章分析。

 

再看下面的代码例子(http://jurisp.iteye.com/blog/815704)

        String s = null;
        System.out.println(s instanceof Object); // false

        System.out.println(s instanceof String); // false

        // 下面的不能经过编译 Incompatible conditional operand types String and String[]
        // boolean as = (s instanceof String[]);

        // 不能编译 Syntax error on token "null", invalid ReferenceType
        // System.out.println(s instanceof null);

        // 不能编译 Incompatible conditional operand types TypeInstanceTest and String//System.out.println(new Solution() instanceof String);

        System.out.println(new String() instanceof String);  //true

        System.out.println(new String() instanceof Object); //true

        // 会抛出异常
        Solution test = (Solution) new Object();

而运行结果以下:

false
false
true
true
Exception

说明不是随便两个类型之间都能用instanceof的,若是两个操做数的类型都是类,其中一个必须是另外一个的子类型

 

另外,注意下面这段晦涩的表述。

访问静态方法,使用表达式做为限定符。表达式的值所引用的对象的运行期类型在肯定哪个方法被调用的时候不起做用,并且对象有标识符,其标识符也不起任何做用。

代码示例以下:

class Solution {
  public static boolean canFinish() {
        System.out.println("here");
        return true;
  }

  public static void main(String[] args) {
        ((Solution) null).canFinish();
  }
}

运行获得正确调用结果:
here

说明,用null是能够调用 static 方法的。

相关文章
相关标签/搜索