如何确定Java中A & B & C这类交集类型的成员?
A & B & C 成员确定的疑问 代码示例
接口定义
interface A { } interface B { } interface C { } interface D extends A, B, C { }
泛型类定义
class N<T extends A & B & C>
JLS相关规则
每个交集类型T1 & ... & Tn都会引入一个虚拟类或接口,用于确定该交集类型的成员,规则如下:
• 对于每个Ti(1 ≤ i ≤ n),令Ci为满足Ti <: Ci的最具体的类或数组类型。必须存在某个Ck,使得对于任意i(1 ≤ i ≤ n)都有Ck <: Ci,否则会发生编译时错误。
• 对于1 ≤ j ≤ n,如果Tj是类型变量,则令Tj'为一个接口,其成员与Tj的公共成员相同;否则,如果Tj是接口,则令Tj'为Tj。
• 如果Ck是Object,则引入一个虚拟接口;否则,引入一个以Ck为直接超类类型的虚拟类。该类或接口拥有直接超接口类型T1', ..., Tn',并声明在交集类型出现的包中。
关于“最具体的类”的定义,相关描述如下:
对于任何表达式,如果S <: T(§4.10),则类型S比类型T更具体。
疑问点
Ci是否可以是接口类型?(规范中明确称Ci只能是类或数组类型)- 若
Ci不能是接口类型,所有Ci都会是Object,但无法确定符合条件的Ck是什么; - 若
Ci可以是接口类型,那么:- T1 == C1 == A
- T2 == C2 == B
- T3 == C3 == C
- Ck == D
但此时Ck是接口而非类类型,和规则中“引入以Ck为直接超类类型的虚拟类”的要求冲突,无论哪种情况都无法正确确定该交集类型的成员。
解答
首先明确:Ci只能是类或数组类型,不能是接口类型。
对于交集类型A & B & C中的每个Ti(A、B、C都是接口),满足Ti <: Ci的最具体类类型就是Object——因为所有接口的隐式超类都是Object,且不存在比Object更具体的类类型满足Ti <: Ci。
此时所有Ci都是Object,那么Ck就是Object(显然Object <: Object对所有i成立)。根据规则,当Ck是Object时,会引入一个虚拟接口,该虚拟接口的直接超接口就是A、B、C(因为Tj都是接口,所以Tj'就是自身)。这个虚拟接口的成员就是A、B、C三个接口成员的并集(遵循接口多重继承的成员合并规则,如重复方法签名需一致等)。
你提到的接口D虽然同时继承了A、B、C,但它并不是Ci的候选——因为Ci要求是类或数组类型,D是接口,不符合Ci的类型限定。所以Ck不会是D,而是Object。
这样就能正确确定A & B & C这个交集类型的成员:即A、B、C三个接口的所有成员的合法合并集合。
内容的提问来源于stack exchange,提问作者user24723440

