What I'd originally thought was a bug in the prototype compiler turns out instead to be an important specification change.
First off, consult the spec and note that the erased type signature for these two methods are different:
<T> T min(Collection<T> coll) { ... } <T extends Comparable> T min(Collection<T> col) { ... }
The return value for the first will have type Object
; the
return value for the second has type Comparable
.
In order to retain binary-compatibility with the previous version of
the JDK, where this method returned Object
, the signature
was changed to:
<T extends Object & Comparable> T min(Collection<T> col) { ... }
This means that the declaration extends Object
is no
longer semantically redundant; it incorporates important information
about the desired type erasure.
For this and other reasons (having to do with type-checking during separate compilation, I think) the signature grammar was changed to allow explicit representation of both the class and interface part of the type bounds. The signatures of these three methods would be, respectively:
<T:Ljava/lang/Object;>(Ljava/util/Collection<TT;>;)TT; <T::Ljava/lang/Comparable;>(Ljava/util/Collection<TT;>;)TT; <T:Ljava/lang/Object;:Ljava/lang/Comparable;>(Ljava/util/Collection<TT;>;)TT;
Note the there are three colon separated fields in the type variable
signature, with the last one optional. The first specifies the
type variable name. The second specifies the class type bound of the
variable. If there is no class type bound, it may be omitted. The
third field specifies the interface type bounds of the variable; if
there are no interface bounds the colon separator is omitted as well.
There is always at least one bound for the type variable:
java.lang.Object
. But there may not be a class type
bound for the variable at all.