Is it intended that the compiler accepts the following type declaration?
class Wrapped<T extends Comparable> { ... }
Wrapped<? super Number> wrapper3; // <<<
Number is not Comparable, and for this reason no supertype of Number is Comparable. Consequently the set of types denoted by Wrapped<? super Number> is empty. Why does the compiler allow nonsensical type declarations?
The specification does not say anything about the lower bound of a wildcard, but I had expected that of course the lower bound of a wildcard is checked against the upper bound of the type parameter the wildcard stands for. No? Wrong idea?
We've flipflopped on this issue a couple of times. At first we though we should check the bounds, but that isn't right, because then you can't write (ignoring the fact that Comparable is generic)
Wrapped<? extends Number>
This is perfectly harmless, and denotes a nontrivial and useful type. So we dropped the checking altogether. That is too relaxed, as you can see. Our current plan, due to Christian Plesner Hansen is:
given this declaration "class C<T extends X>",
C<Y> is legal if Y <: X (the current rule) C<? extends Y> is legal if Y is castable to X
* C<? super Y> is legal unless Y cannot possibly be a subtype of X
The prototype compiler doesn't currently have this rule nor "castable" implemented, nor are they specified in the jsr14 spec that I distributed. I'm working on this now, based on very nice code supplied by Christian, but I'm afraid I may not have it in the prototype until October.
These results look like they're related to the issue you've gone back and forth on. FWIW, the thing that suprised me most was that one was accepted and the other wasn't -- I somewhat expected I<Integer> to work, but if it isn't allowed, I can't resolve why I<Number> does work. My niave expectation was that Integer ought to be substitutable for Number here.
David Hall
publicclass VarTest {
class I<T> {}
I<? super Number> i1 = new I<Number>();
I<? super Number> i2 = new I<Integer>();
}
$ javac VarTest.java
VarTest.java:5: incompatible types
found : VarTest.I<java.lang.Integer>
required: VarTest.I<? super java.lang.Number>
I<? super Number> i2 = new I<Integer>();
^
1 error
This is not an issue of checking the bounds, this is a subtyping issue. I<Integer> is not a subtype of I<? super Number> because Integer is not a supertype of Number.