在Java语言规范第11版第4.10.2节中,部分内容是在讨论参数化类型的直接超类型时进行的:
给定一个泛型类型声明C<F₁,…,Fₙ>(n>0),参数化类型C<T₁,…,Tₙ>其中Tᵢ(1≤i≤n)是一种类型,都是以下类型:
(然后它列出了一组适用于此类参数化类型的规则。这些规则大多与此问题无关。它们的相关性仅在于它们为某些参数化类型定义了直接超类型。)
什么";是一种类型";方法可以在第4.1节的顶部找到:
Java编程语言中有两种类型:基元类型(§4.2)和引用类型(§4.3)。
引用类型(我们这里肯定不是在谈论基元)只是ClassOrInterfaceType
、TypeVariable
或ArrayType
。
因此,通配符不是一种类型。
(事实上,这是一种TypeArgument
。你可能会像我曾经做的那样,模糊而天真地认为通配符是一种不稳定的TypeVariable
,因此也是一种类型,但你错了。)
因此,把所有这些放在一起,我对第4.10.2节相关部分的解读是:
- "参数化类型C<T₁,…,Tₙ>,其中Tᵢ(1≤i≤n)是一个类型";有各种各样的直接超类型
- …但是参数化类型C<T₁,…,Tₙ>,其中至少一个Tₙ是一个通配符,有没有直接超类型…
- …因为本节中列出的规则不完全或部分应用于至少包含一个通配符的参数化类型…
- …因为通配符不是类型,所以;其中Tᵢ(1≤i≤n)是一个类型";条件永远不会满足
- …因为本节中列出的规则不完全或部分应用于至少包含一个通配符的参数化类型…
这是正确的读数吗?换句话说,我的演绎推理正确吗?
(顺便说一句,可能值得注意的是,有些类型可以"包含"包含通配符的参数化类型(如第4.5.1节所定义)。)
您引用的部分确实没有说明任何关于至少有一个通配符类型参数的参数化类型的内容。它们的直接超类型是什么,在你引用的部分后面有具体说明:
给定一个泛型类型声明C<F1,。。。,Fn>(n>0),参数化类型C<R1,。。。,Rn>其中Ri(1≤i≤n)中的至少一个是通配符类型自变量,是参数化类型C<X1、,。。。,Xn>其是将捕获转换应用于C<R1,。。。,Rn>(§5.1.10).
基本上,要找到至少有一个通配符类型参数的类型的直接超类型,您首先应用捕获转换,然后您将获得一个仅为"的参数化类型;"类型";作为类型参数,as捕获转换将通配符转换为类型变量。之后,您可以使用引用的规则来查找其超类型。
通配符是JAVA中的类型,它们是"存在类型";。来自同一个链接页面:
通配符与已建立的类型论的关系是有趣的一个,我们在这里简要地提到。通配符是存在类型的限制形式。给定泛型类型声明G、 G<gt;大致类似于某些X<:B.G.
还有:
原始类型与通配符密切相关。两者都基于存在类型。原始类型可以被认为是通配符,其类型规则故意不健全,以适应与遗产的互动密码历史上,原始类型在通配符之前;他们是第一个在GJ中介绍,并在论文《让未来安全》中进行了描述过去:通过吉拉德·布拉查、马丁·奥德斯基、大卫·斯塔迈尔和菲利普·沃德勒ACM面向对象编程会议论文集,《系统、语言和应用》(OOPSLA 98),1998年10月。
存在类型对调用方隐藏其实现中的类型。对于存在于T中的X,X的同一性不能从任何调用对象中得知。所有已知的都是在定义中提供的一组操作。
从Java中的原始类型:原始类型是没有类型参数的通用接口或类的名称:
List list = new ArrayList(); // raw type
代替:
List<Integer> listIntgrs = new ArrayList<>(); // parameterized type
因此,它不是JAVA中典型意义上的类型:基元或引用类型,但它是一种特殊形式的类型,编译器有规则并知道如何处理。这是否意味着它真的不是一种类型?我认为不,它是一个伪类型或未知类型,因为没有更好的词,因为它可以在不知道它的类型是什么的情况下声明和使用
因此,它本身不会有超类型。
但是参数化类型C<T₁,…,Tₙ>,其中至少一个Tₙ是通配符没有直接的超类型…
然而,正如@Sweeper所指出的,如果您至少有一个通配符类型参数来参数化类型,那么您可以使用捕获转换来找到超级类型。
我在SO上找到了捕获转换的定义:Java中的捕获转换是什么?有人能给我举个例子吗?
捕获转换使编译器能够制造捕获的通配符的占位符类型名称,因此类型推断可以推断出它是那种类型。