covariant returns for CharBuffer.subSequence
Alex Buckley
Alex.Buckley at Sun.COM
Mon Aug 4 18:50:22 UTC 2008
Hi Remi,
Rémi Forax wrote:
> Because in my opinion, there is a bug in the JLS3 regarding covariant
> return type.
No, there isn't.
> Let us take an example, a library defines Buffer and SubBuffer
> public class Buffer {
> Buffer duplicate() { ... }
> }
> public class SubBuffer extends Buffer {
> }
>
> And i've a code that use that library
> public class MySubBuffer extends SubBuffer {
> Buffer duplicate() { ... }
> }
>
> If the developer of the library want to use covariant return type
> introducing a method:
> SubBuffer duplicate()
> in SubBuffer, it will break my code.
Naturally, because your code is now type-unsafe.
> The weird thing is that if you generify Buffer and SubBuffer,
> you can have a covariant return type in a backward compatible way :
> class Buffer<T extends Buffer<T>> {
> T duplicate() { ... }
> }
> class SubBuffer<T extends SubBuffer<T>> extends Buffer<T> {
> }
>
> Why ?
> Because the JLS allows to override a generic method with
> a method with the erased generic signature in order to allow to
> generify a library even if code that use it is not generified
> (see JLS section 8.4.2).
To be precise, duplicate() is not a generic method, since it does not
introduce its own type parameters. It is just a method which happens to
use a type parameter from the class. But yes, override-equivalence
allows such a method to be overridden by a method with an erased signature.
However, that doesn't help MySubBuffer, since its duplicate() does not
have return-type-substitutability with duplicate() in SubBuffer. If you
declare 'T duplicate() {..}' in SubBuffer, you'll get an error when
compiling MySubBuffer. I believe javac should actually give an error on
MySubBuffer even without a duplicate() declaration in SubBuffer, since
duplicate() is there by inheritance.
In any case, if you go ahead and point a SubBuffer<? extends
SubBuffer<?>> variable at a raw MySubBuffer, there is no possibility of
NoSuchMethodError. This is because javac is smart enough to call the
duplicate() in SubBuffer, not MySubBuffer. But you'll get an unchecked
warning, because the raw assignment could lead to ClassCastExceptions in
general.
> The problem is that there is no such rule for covariant return type,
> so refactoring to use covariant return type in a library is impossible.
If there was such a rule, it would be type-unsafe.
Alex
More information about the core-libs-dev
mailing list