Java汇编指令instanceof的规则是什么意思?

3
当深入到Java字节码汇编指令级别的操作符instanceof时,它对应于一个Java汇编指令instanceof。但我读到了用于确定非空对象引用是否为已解析类型实例的规则:
第二条规则如下:
如果S是接口类型,则:
  • 如果T是类类型,则T必须是Object。
  • 如果T是接口类型,则T必须是与S相同的接口或S的超级接口。
这让我感到困惑。 "S是接口类型"是否意味着S的引用类型是接口类型?如果是这样,那么第一条规则“如果T是类类型,则T必须是Object”就无法成立。例如:
CharSequence charSequence = new StringBuilder("test");
System.out.println(charSequence instanceof StringBuilder);
System.out.println(charSequence instanceof String);

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

“S是由objectref引用的对象的类”:在这种情况下,StringBuilder。打印“false”的第三行是正确的。 - user207421
@EJP 但是您不认为我提到的第一条规则与我给出的代码应该打印出的内容不同吗?String是Object,不是吗? - Rui
1个回答

2
你可能会感到困惑,因为这些规则的写法很令人费解。
对于一个 "objectref",它不可能有一个接口类型,因为每个实例化对象都有一个实际的、非抽象的类型,可能实现了一个接口。这甚至适用于 lambda 表达式生成的实例,它们具有未指定(匿名)类型,实现了函数接口。
因此,乍一看,这些规则的这部分似乎毫无意义。但请考虑完整的文本:
以下规则用于确定一个非 null 的 "objectref" 是否是已解析类型的实例:如果 "objectref" 引用的对象的类为 "S",并且 "T" 为已解析的类、数组或接口类型,则 "instanceof" 将按以下方式确定 "objectref" 是否为 "T" 的实例:
- 如果 "S" 是普通(非数组)类,则: - 如果 "T" 是类类型,则 "S" 必须与 "T" 相同或 "S" 必须是 T 的子类; - 如果 "T" 是接口类型,则 "S" 必须实现接口 "T"。 - 如果 "S" 是接口类型,则: - 如果 "T" 是类类型,则 "T" 必须为 Object。 - 如果 "T" 是接口类型,则 "T" 必须与 "S" 相同或是 "S" 的超级接口。 - 如果 "S" 是表示数组类型 "SC[]" 的类,即类型为 "SC" 的组件的数组,则: - 如果 "T" 是类类型,则 "T" 必须为 Object。 - 如果 "T" 是接口类型,则 "T" 必须是数组实现的接口之一(JLS §4.10.3)。 - 如果 "T" 是数组类型 "TC[]",即类型为 "TC" 的组件的数组,则以下情况之一必须成立: - "TC" 和 "SC" 是相同的基本类型。 - "TC" 和 "SC" 都是引用类型,并且类型 "SC" 可以按照这些运行时规则转换为 "TC"。

由于objectref引用的实际对象不可能具有接口类型,因此只适用另外两个要点;它的类型是“普通(非数组)类”或数组类型。在后一种情况下,最后一句话是有趣的,因为它涉及到整个引用类型转换规则,并将其应用于TS的组件类型(如果两者都是引用类型的数组)。而且组件类型可以是接口类型。

因此,您可以使用一个实际的接口类型的数组实例来测试这些规则,并与其他数组类型进行比较:

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

如果在可能应用的数组特例中描述接口案例,那么它会更少引起困惑。另一方面,这三种情况遵循通用的正式赋值规则,在这种形式下更容易识别。


所以这只能工作是因为数组是协变的,对吧?但我想不出一个地方我曾经看到过针对数组的instanceOf。 - Eugene
@Eugene:这是使数组协变的规则之一。 - Holger

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接