Question

If we have generic method

class SClass{
    public static <T> ArrayList<T> listFactory(){ return new ArrayList<T>(); }
}

we can define type-parameter T explicit when this method is calling.

SClass.<?>listFactory();//compile error
SClass.<List<?>>listFactory();//ok

Why we cant invoke listFactory with type parameter ?, but can with List<?>?

Was it helpful?

Solution

The rules of method invocation are described in the Java Language Specification. In this case we are interested with

A method invocation expression is used to invoke a class or instance method.

[...]
TypeName . NonWildTypeArguments Identifier ( ArgumentListopt )

<?> is a wild type, <List<?>> is not.

As for the reason why, consider

SClass.<?>listFactory();//compile error

What could you even do with <?> in listFactory()? ? is unknown. You wouldn't be able to do

new ArrayList<?>(); 

because the JLS prohibits it

It is a compile-time error if any of the type arguments used in a class instance creation expression are wildcard type arguments (§4.5.1).

But you couldn't use it with anything else either.

OTHER TIPS

Why we cant invoke listFactory with type parameter ?, but can with List?

Instance Creation In a class instance creation expression, if the type is a parameterized type, then none of the type parameters may be wildcards. I think its the same like:

List<?> list = new ArrayList<?>(); // compile-time error

Only top-level parameters in instance creation are prohibited from containing wildcards. Nested wildcards are permitted. Hence, the following is legal:

List<List<?>> lists = new ArrayList<List<?>>(); // ok

This is a reason why:

SClass.<List<?>>listFactory();//ok

From Java Generics and Collections

Generic Method Calls If a generic method call includes explicit type parameters, those type parameters must not be wildcards.

class SClass{
    public static <T> ArrayList<T> listFactory(){ return new ArrayList<T>(); }
}

You may choose for the type parameters to be inferred, or you may pass an explicit type parameter. Both of the following are legal:

List<?> list = Lists.factory();
List<?> list = Lists.<Object>factory();

If an explicit type parameter is passed, it must not be a wildcard:

List<?> list = Lists.<?>factory(); // compile-time error

Nested wildcards are permitted:

List<List<?>> = Lists.<List<?>>factory(); // ok

The Java designers had in mind that every wildcard type is shorthand for some ordinary type, so they believed that ultimately every object should be created with an ordinary type. It is not clear whether this restriction is necessary, but it is unlikely to be a problem.

Instead of SClass.<?>listFactory() you can just use:

class CompletelyUnrelatedBogusClass { }

SClass.< CompletelyUnrelatedBogusClass >listFactory();

Since ? is unknown, it means it makes no assumptions about what it is. Which means you can put any reference type in there, and it would be correct.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top