Search code examples
javasyntaxjls

Java syntax: NonWildcardTypeArguments


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


Solution

  • 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.)