Java汇编指令instanceof规则的含义是什么?

Java汇编指令instanceof规则的含义是什么?,java,java-bytecode-asm,Java,Java Bytecode Asm,当深入到Java字节码汇编指令级别上的运算符instanceof时,它对应于Java汇编指令。但我读过以前的规则 确定不为null的objectref是否为已解析类型的实例: 第二条规则告诉我们: 如果S是接口类型,则: 如果T是类类型,那么T必须是对象 如果T是接口类型,则T必须与S相同或是S的超级接口 这让我很困惑。“S是接口类型”是否意味着S的参考类型是接口类型?如果是这样,第一条规则“如果T是类类型,那么T必须是对象”就不能成立。比如说, CharSequence charSeque

当深入到Java字节码汇编指令级别上的运算符
instanceof
时,它对应于Java汇编指令。但我读过以前的规则

确定不为null的objectref是否为已解析类型的实例:

第二条规则告诉我们:

如果S是接口类型,则:

  • 如果T是类类型,那么T必须是对象
  • 如果T是接口类型,则T必须与S相同或是S的超级接口
这让我很困惑。“S是接口类型”是否意味着S的参考类型是接口类型?如果是这样,第一条规则“如果T是类类型,那么T必须是对象”就不能成立。比如说,

CharSequence charSequence = new StringBuilder("test");
System.out.println(charSequence instanceof StringBuilder);
System.out.println(charSequence instanceof String);

上面代码中的第二行将打印true,而上面的第三行将打印false。因此,我怀疑我的理解可能是错误的,任何人都可以帮助解释上述规则的含义吗?

你有权感到困惑,因为这些规则的编写方式令人困惑

对于objectref,不可能有接口类型,因为每个实例化对象都有一个实际的非抽象类型,可能实现了一个接口。这甚至适用于为lambda表达式生成的实例,该表达式具有实现函数接口的未指定(匿名)类型

因此,乍一看,这部分规则似乎毫无意义。但是考虑全文:

以下规则用于确定非
null
的objectref是否为已解析类型的实例:如果
S
是objectref引用的对象的类,
T
是已解析的类、数组或接口类型,instanceof确定objectref是否是
T
的实例,如下所示:

  • 如果
    S
    是普通(非阵列)类,则:
    • 如果
      T
      是类类型,那么
      S
      必须与
      T
      是同一类,或者
      S
      必须是T的子类
    • 如果
      T
      是一种接口类型,则
      S
      必须实现接口
      T
  • 如果
    S
    是一种接口类型,则:
    • 如果
      T
      是类类型,则
      T
      必须是对象
    • 如果
      T
      是一种接口类型,则
      T
      必须与
      S
      是同一接口或
      S
      的超级接口
  • 如果
    S
    是表示数组类型
    SC[]
    的类,即
    SC
    类型的组件数组,则:
    • 如果
      T
      是类类型,则
      T
      必须是对象
    • 如果
      T
      是一种接口类型,则
      T
      必须是阵列实现的接口之一(JLS§4.10.3)
    • 如果
      T
      是数组类型
      TC[]
      ,即
      TC
      类型的组件数组,则必须满足以下条件之一:
      • TC
        SC
        是相同的基元类型
      • TC
        SC
        是引用类型,类型
        SC
        可以通过这些运行时规则强制转换为
        TC
由于objectref引用的实际对象不可能具有接口类型,因此仅应用其他两个项目符号;其类型为“普通(非数组)类”或数组类型。在后一种情况下,最后一句是有趣的一句,因为它指的是引用的规则作为一个整体,适用于
T
S
的组件类型,如果两者都是引用类型的数组。并且组件类型可以是接口类型

因此,您可以使用接口类型的实际数组实例测试这些规则,并对照其他数组类型进行检查:

Object o = new Collection[0]; // SC is Collection
System.out.println(o instanceof Object[]); // TC is class type Object -> true
System.out.println(o instanceof String[]); // TC is class type other than Object -> false
System.out.println(o instanceof Collection[]); // TC == SC -> true
System.out.println(o instanceof Iterable[]); // TC is super interface of SC -> true
System.out.println(o instanceof List[]); // TC is not super interface SC -> false

它认为,如果接口情况是在数组特殊情况中描述的,那么就不那么容易混淆了,因为在数组特殊情况中可能会用到接口情况。另一方面,这三种情况遵循一般的形式赋值规则,因此在这种形式下更容易识别。

'S是objectref引用的对象的类:在这种情况下,
StringBuilder
。第三行打印
false
是正确的。@EJP但您不认为我提到的第一条规则与我给出的代码中应该打印的规则不同吗?字符串是对象,这不是因为数组是协变的才行吗?我想不出有哪一个地方我看到过一个数组中的isntanceOfthough@Eugene:这是使数组协变的规则之一。