7

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.

Josh Bradley
  • 4,630
  • 13
  • 54
  • 79

1 Answers1

4

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.

Saintali
  • 4,482
  • 2
  • 29
  • 49
  • Pretty good answer but I don't think the reasoning in the second half makes much sense. If a variable `a` is typed as `A extends B>` that doesn't mean `a.value` is *declared* as `? extends B` - `value` is declared as `T` where `A` declares `T`. `a.value` does *evaluate* to `? extends B`. See my answer to a similar question [here](http://stackoverflow.com/a/9147768/697449). – Paul Bellora Oct 07 '12 at 03:33
  • @PaulBellora Admitted, I was not very clear in the second part. What I intended to say was that there is a difference between the putative type of the _expression_ `a.value` and the declared type of the the _variable_ `a.value`. Note that a variable is both an r-value and an l-value, so if you where allowed to create a variable/field with a wildcard type `? extends T` (or `? super T`) it would be an inherently handicapped variable. You would not be able to use it as an r-value, (l-value respectively). Now, that is tolerable for an ordinary reference `a`, but never for `this`. – Saintali Oct 07 '12 at 06:31