The following is defined in chapter 18 of jls https://docs.oracle.com/javase/specs/jls/se7/html/jls-18.html
NonWildcardTypeArguments:
< TypeList >
TypeList:
ReferenceType { , ReferenceType }
ReferenceType:
Identifier [TypeArguments] { . Identifier [TypeArguments] }
TypeArguments:
< TypeArgument { , TypeArgument } >
TypeArgument:
ReferenceType
? [ (extends | super) ReferenceType ]
According to the name of NonWildcardTypeArguments, it should not allow wild card. But the following code compiles
public class NonWildcardTypeArgumentsTest {
public void test(Test<java.util.Set<? extends Object>> args) {
}
}
class Test<T> {}
The type arguments in this example satisfies the definition of NonWildcardTypeArguments and it contains wild card:
<java.util.Set<? extends Object>>
I am confused by this. Why is it valid? Thanks
The wildcard is a type argument to Set
, not Test
. The grammar here is a tree-like structure, where each type argument applies to the type outside of it.
Test<T>
↓
Set<E>
↓
? extends Object
NonWildcardTypeArguments
only requires that each type argument is a ReferenceType
, which Set<? extends Object>
satisfies, since it's of the form Identifier<TypeArgument>
. (? extends Object
is a TypeArgument
, but not a ReferenceType
.)
For example, <Set<? extends Object>>
is a NonWildcardTypeArguments
but <? extends Set<Object>>
is not.
So yes, there is a wildcard "in" the type arguments, but it's nested down a level in the tree. The NonWildcardTypeArguments
construct only cares about the arguments directly inside of it.
Anyway, as assylias pointed out, this grammatical construct does not seem to exist anymore but I suppose the explanation is still interesting. (I tried searching the JLS 8 PDF for 'NonWildcardTypeArguments' and didn't come up with anything.)