在jls https://docs.oracle.com/javase/specs/jls/se7/html/jls-18.html的第18章中定义了以下内容
NonWildcardTypeArguments:
< TypeList >
TypeList:
ReferenceType { , ReferenceType }
ReferenceType:
Identifier [TypeArguments] { . Identifier [TypeArguments] }
TypeArguments:
< TypeArgument { , TypeArgument } >
TypeArgument:
ReferenceType
? [ (extends | super) ReferenceType ]
根据NonWildcardTypeArguments的名称,它不应允许通配符。但是下面的代码编译
public class NonWildcardTypeArgumentsTest {
public void test(Test<java.util.Set<? extends Object>> args) {
}
}
class Test<T> {}
此示例中的类型参数满足NonWildcardTypeArguments的定义,并且包含通配符:
<java.util.Set<? extends Object>>
我对此感到困惑。为什么有效?谢谢
最佳答案
通配符是Set
的类型参数,而不是Test
。这里的语法是一个树状结构,其中每个类型实参都适用于其外部的类型。
Test<T>
↓
Set<E>
↓
? extends Object
NonWildcardTypeArguments
仅要求每个类型参数是ReferenceType
即可满足,因为Set<? extends Object>
的形式为Identifier<TypeArgument>
。 (? extends Object
是TypeArgument
,但不是ReferenceType
。)例如,
<Set<? extends Object>>
是NonWildcardTypeArguments
,但<? extends Set<Object>>
不是。因此,是的,类型参数中有一个通配符,但它嵌套在树的某个级别下。
NonWildcardTypeArguments
构造仅在乎其内部的参数。无论如何,正如assylias所指出的那样,这种语法结构似乎已经不存在了,但我认为这种解释仍然很有趣。 (我尝试在JLS 8 PDF中搜索“NonWildcardTypeArguments”,但未提出任何建议。)