I was reviewing someone else's code the other day and I came across a line that raised some concern. To simplify, say I have a generic Class A and an abstract Class B. Is the following instantiation allowed and if so, why?
Object obj = new A<? extends B>();
I personally have never seen an instantiation like the above, although a declaration such as
A<? extends B> obj = null;
would certainly hold. I've always used the wildcard in generics to declare method parameters, so I may just not have the experience.
In generic code, the question mark (?), called the wildcard, represents an unknown type. The wildcard can be used in a variety of situations: as the type of a parameter, field, or local variable; sometimes as a return type (though it is better programming practice to be more specific).
There are 3 types of wildcards in Java: Upper bounded wildcards, Lower Bounded Wildcards, and Unbounded Wildcards.
To use Java generics effectively, you must consider the following restrictions: Cannot Instantiate Generic Types with Primitive Types. Cannot Create Instances of Type Parameters.
both bounded and unbounded wildcards provide a lot of flexibility on API design especially because Generics is not covariant and List<String> can not be used in place of List<Object>. Bounded wildcards allow you to write methods that can operate on Collection of Type as well as Collection of Type subclasses.
Actually new A<? extends B>()
does not compile. It has been consistently illegal since Java 5.
But I guess your original example was something like new A<X<? extends B>>()
. The latter is legal in recent versions of Java.
The idea is, when instantiating an object, the value for type parameters can be any non-wildcard type. ? extends B
is a wildcard type, so it is disallowed. But X<? extends B>
is not a wildcard type, though it has a wildcard type as a component. So you can say legally call new A<X<? extends B>>()
.
The rules makes sense if you think about it this way. Ultimately it is a byproduct of the more fundamental rule that a wildcard type like ? extends B
cannot be the declared type of a field or variable. If A
is defined as
class A<T> {
T value;
}
then the hypothetical new A<? extends B>().value
would be a field declared of type ? extends B
. Since that is illegal, so is the instantiation. But new A<X<? extends B>>()
does not have that problem.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With