Java 7的交集类型:规范究竟是什么意思?

4

http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.9

  • 对于每个Ti(1≤i≤n),让Ci成为最具体的类或数组类型,使得Ti <: Ci。然后必须存在一些Tk <: Ck,使得Ck <: Ci对于任何i(1≤i≤n),否则会出现编译时错误。

  • 对于1≤j≤n,如果Tj是类型变量,则让Tj'成为一个接口,其成员与Tj的公共成员相同;否则,如果Tj是接口,则让Tj'成为Tj。

  • 然后交集类型具有与类类型(§8)相同的成员,其中包含一个空主体,直接超类Ck和直接超接口T1',...,Tn',在相同的包中声明交集类型。

我本来希望以下代码会导致编译时错误,但实际上并没有:

public interface I1 {}
public interface J1 extends I1 {}
public interface J2 {}
public interface J3 extends J2 {}

class C implements J1, J3 {}

public class A<T extends J1 & J3> {
    public static void main(String[] args) {
        A<C> a = new A<>();
    }

}

据我所了解,Ti <: Ci类型如下:
  • J1 <: I1
  • J3 <: J2
现在,我需要有一个Tk <: Ck,其中Ck <: C1和Ck <: C2,但如果Ck := C1,则I1 <: J2为假,如果Ck := C2,则J2 <: I1为假。
这里我漏掉了什么?
1个回答

4
您似乎混淆了<:<。如果您阅读下一节关于子类型的内容,您将看到<:对于类本身是有效的 - 换句话说,对于任何类型T,T <: T都为真。这与<相反,后者用于严格的子类化(T < T始终为假)。
在您的示例中:
  • T1 == C1 == J1
  • T2 == C2 == J2
  • Tk == Ck == C
您可以验证C <: J1C <: J2
所以一切看起来都很好。

1
是的,我忘记了<:是反身代词。您能否通过举例说明什么会根据引用标准导致编译时错误来帮助澄清情况? - dsplynm
我本以为像 A<T extends String & List> 这样的东西不会编译(因为String是final类型,且没有实现List接口),但在jdk 8上它仍然可以编译通过。所以其实我也不确定... - assylias
@assylias 我认为这个编译是因为Object是String和List的超类型,并且总是存在一个类Ck,它是Object的子类型。 - klabe

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