Covariant overrides on the Buffer Hierachy

Peter Levart peter.levart at gmail.com
Mon Apr 21 11:10:23 UTC 2014


On 04/20/2014 08:56 PM, Richard Warburton wrote:
> Hi,
>
> It looks to me like there are no obvious problems with changing the buffer
>> subclasses to use covariant overrides. As Alan mentioned, one API was
>> modified this way in 7, by Martin Buchholz. The discussion threads for this
>> change are [2] and [3]. It looks like Martin considered additional
>> covariant overrides, but ultimately backed off from this for a variety of
>> incidental reasons; see [4]. There is a certain amount of work here above
>> and beyond just changing the return types, but there don't appear to be any
>> fundamental issues.
> So I've put a patch on cr at
> http://cr.openjdk.java.net/~rwarburton/buffer-overrides-0/

Hi,

Since the public part of Buffer type hierarchy is (mostly) just 
two-level, an alternative would be to generify java.nio.Buffer:

public abstract class Buffer<B extends Buffer<B>> {

     @SuppressWarnings("unchecked")
     protected final B self() { (B) return this; }

public final B position(int newPosition) {
         ...
         return self();
     }
     ...
}

public abstract class LongBuffer
     extends Buffer<LongBuffer>
     implements Comparable<LongBuffer>
{
...
}

public abstract class ShortBuffer
     extends Buffer<ShortBuffer>
     implements Comparable<ShortBuffer>
{
...
}

...

The question is what to do with ByteBuffer/MappedByteBuffer then. One 
alternative is to fix the type variable constraint at ByteBuffer level 
and leave MappedByteBuffer astray:

public abstract class ByteBuffer
     extends Buffer<ByteBuffer>
     implements Comparable<ByteBuffer>
{
...
}

public abstract class MappedByteBuffer
     extends ByteBuffer
{
...
}


...in this case Buffer/ByteBuffer methods invoked on MappedByteBuffer 
would have ByteBuffer return type. This would only matter if one wanted 
to call MappedByteBuffer's methods at the end of the chain - there are 
three of them: isLoaded()/load()/force().

The other alternative is to fix the type variable constraint at 
MappedByteBuffer level:

public abstract class ByteBuffer
     extends Buffer<B extends ByteBuffer<B>>
     implements Comparable<ByteBuffer<?>>
{
...
}

public abstract class MappedByteBuffer
     extends ByteBuffer<MappedByteBuffer>
{
...
}


...in this case, the following:

     ByteBuffer bb = ...;

would be a raw type and consequently Buffer methods, when invoked on bb, 
would have Buffer return type (the erasure), but that's not a problem - 
it is source compatible. To achieve the desired effect one would have to 
use at least:

     ByteBuffer<?> bb = ...;




I'm suggesting this alternative, because Buffer methods can stay final 
in this case. This is more JIT-friendly. And, if I'm not mistaken, 
client code compiled using JDK8 onto which this API change was 
backported, would still run with JDK8 (or JDK7 when compiled with 
-target 1.7) onto which the API change was not back-ported.


Regards, Peter


> . It also touches
> a couple of other classes which have unnecessary casts in. Aside from being
> a good idea, fixing the casts is also necessary due to -Werror.  Let me
> know if I've missed anything or if there are any outstanding issues.
>
> I think the bugs that this resolves are:
>
> https://bugs.openjdk.java.net/browse/JDK-4774077
> https://bugs.openjdk.java.net/browse/JDK-6451131
>
> regards,
>
>    Richard Warburton
>
>    http://insightfullogic.com
>    @RichardWarburto <http://twitter.com/richardwarburto>




More information about the core-libs-dev mailing list