Java 汇编指令instanceof 的规则是什么意思?
What is the meaning of the rules for Java assembly instruction instanceof?
在Java字节码汇编指令层面下钻到运算符instanceof
时,对应一条Java汇编指令instanceof
。但是我看规则习惯了
determine whether an objectref that is not null is an instance of the resolved type:
第二条规则告诉:
If S is an interface type, then:
- If T is a class type, then T must be Object.
- If T is an interface type, then T must be the same interface as S or a superinterface of S.
这让我很困惑。 “S是接口类型”是否意味着S的引用类型是接口类型?如果是这样,第一条规则“如果 T 是 class 类型,则 T 必须是对象”不能成立。例如,
CharSequence charSequence = new StringBuilder("test");
System.out.println(charSequence instanceof StringBuilder);
System.out.println(charSequence instanceof String);
上面代码中的第二行将打印 true,而上面的第三行将打印 false。所以我怀疑我的理解可能是错误的,谁能帮忙解释一下上面规则的意思?
您有权感到困惑,因为这些规则的编写方式,令人困惑。
对于 objectref,不可能 具有接口类型,因为每个实例化对象都有一个实际的非抽象类型,也许实现一个接口。这甚至适用于为 lambda 表达式生成的实例,这些实例具有实现功能接口的未指定(匿名)类型。
所以乍一看,这些规则的这一部分似乎没有任何意义。但考虑全文:
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 T
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 T
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.
由于objectref引用的实际对象不可能有接口类型,所以只适用另外两条;它的类型是“普通(非数组)class”或数组类型。在后一种情况下,最后一句话很有趣,因为它指的是引用的规则作为一个整体,应用于 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
它认为,如果在可能适用的数组特殊情况下描述接口情况,那将不会那么混乱。另一方面,这三种情况都遵循了一般的正式赋值规则,因此以这种形式更容易识别。
在Java字节码汇编指令层面下钻到运算符instanceof
时,对应一条Java汇编指令instanceof
。但是我看规则习惯了
determine whether an objectref that is not null is an instance of the resolved type:
第二条规则告诉:
If S is an interface type, then:
- If T is a class type, then T must be Object.
- If T is an interface type, then T must be the same interface as S or a superinterface of S.
这让我很困惑。 “S是接口类型”是否意味着S的引用类型是接口类型?如果是这样,第一条规则“如果 T 是 class 类型,则 T 必须是对象”不能成立。例如,
CharSequence charSequence = new StringBuilder("test");
System.out.println(charSequence instanceof StringBuilder);
System.out.println(charSequence instanceof String);
上面代码中的第二行将打印 true,而上面的第三行将打印 false。所以我怀疑我的理解可能是错误的,谁能帮忙解释一下上面规则的意思?
您有权感到困惑,因为这些规则的编写方式,令人困惑。
对于 objectref,不可能 具有接口类型,因为每个实例化对象都有一个实际的非抽象类型,也许实现一个接口。这甚至适用于为 lambda 表达式生成的实例,这些实例具有实现功能接口的未指定(匿名)类型。
所以乍一看,这些规则的这一部分似乎没有任何意义。但考虑全文:
The following rules are used to determine whether an objectref that is not
null
is an instance of the resolved type: IfS
is the class of the object referred to by objectref andT
is the resolved class, array, or interface type, instanceof determines whether objectref is an instance ofT
as follows:
- If
S
is an ordinary (nonarray) class, then:
- If
T
is a class type, thenS
must be the same class asT
, orS
must be a subclass of T;- If
T
is an interface type, thenS
must implement interfaceT
.- If
S
is an interface type, then:
- If
T
is a class type, thenT
must be Object.- If
T
is an interface type, thenT
must be the same interface asS
or a superinterface ofS
.- If
S
is a class representing the array typeSC[]
, that is, an array of components of typeSC
, then:
- If
T
is a class type, thenT
must be Object.- If
T
is an interface type, thenT
must be one of the interfaces implemented by arrays (JLS §4.10.3).- If
T
is an array typeTC[]
, that is, an array of components of typeTC
, then one of the following must be true:
TC
andSC
are the same primitive type.TC
andSC
are reference types, and typeSC
can be cast toTC
by these run-time rules.
由于objectref引用的实际对象不可能有接口类型,所以只适用另外两条;它的类型是“普通(非数组)class”或数组类型。在后一种情况下,最后一句话很有趣,因为它指的是引用的规则作为一个整体,应用于 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
它认为,如果在可能适用的数组特殊情况下描述接口情况,那将不会那么混乱。另一方面,这三种情况都遵循了一般的正式赋值规则,因此以这种形式更容易识别。