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