To understand why it is not allowed to create objects of wildcard parameterized types, you must first understand what's the use of wildcard parameterized types.
Why wildcards?
As you already know that Java generics are invariant. So a List<Number>
is not a super class of List<Integer>
, even though their type arguments are covariant. So, what if you want such a behaviour in generics too, like having the same reference pointing to different objects? That polymorphic thing, as you would name it. What if you want a single List
reference to refer to list of Integer
, Float
, or Double
?
Wildcards to the rescue:
With wildcards, you can achieve the above mentioned behaviour. So, a List<? extends Number>
can refer to a List<Integer>
, List<Double>
, etc. So, the following declarations are valid:
List<? extends Number> numbers = new ArrayList<Integer>();
numbers = new ArrayList<Double>();
numbers = new ArrayList<Float>();
numbers = new ArrayList<String>(); // This is still not valid (you know why)
So what did we change here? Just the reference type of the numbers
. Note that generics were introduced in Java for enforcing stronger compile time check. So, it's primarily the compiler's job to decide whether the declaration of a parameterized type is conforming to the rule or not. Without wildcard, compiler shows you error for a List<Number>
refering to List<Integer>
.
So, wildcards are just a way to introduce co-variance like behaviour into generics. By using wildcards, you increase the flexibility, or you can say, reduce the restriction that compiler enforces. A List<? extends Number>
reference tells the compiler that the list can refer to a list of Number
or any subtype of Number
(Of course, there are lower bounded wildcards too. But that's not the point here. The differences between them is already discussed in many other answers on SO only).
Major uses of wildcard parameterized type you would see with method parameters, where you want to pass different instantiation of a generic type for a single method parameter:
// Compiler sees that this method can take List of any subtype of Number
public void print(List<? extends Number> numbers) {
// print numbers
}
But at runtime, for creating an object you have to give a concrete type. A wildcard - bounded, or unbounded, is not a concrete type. ? extends Number
could mean anything that is subtype of Number
. So what type of List
would you expect to be created when you create a List<? extends Number>
?
You can consider this case similar to the reason why you can't instantiate an interface
. Because they aren't just concrete.
There is a workaround. Really?
Although this is illegal, you would be surprised to know that there is a workaround, as explained in - Java Generics FAQs. But I really don't think you would ever need that.