I have a java.nio.ByteBuffer in my code:
ByteBuffer bb = ByteBuffer.allocateDirect(1024);
...
I want to be able to swap it in place for a new implementation of ByteBuffer (i.e. it must extend java.nio.ByteBuffer) so that it will re-allocate, copy and discard the previous small ByteBuffer under-the-hood, to allow for seamless dynamic growing.
I can't just have a wrapper because it must be a java.nio.ByteBuffer
.
It would have to be something like that:
ByteBuffer bb = new MyImplementationOfByteBufferThatExtendsByteBuffer(1024);
Has anyone seen or done that? Is it possible?
Just want to note that if java.nio.ByteBuffer
was an interface instead of an abstract class, that would be trivial to implement. Like the old saying goes, favor interfaces over abstract classes if you want flexibility.
No, this does not exist, and cannot exist without violating the contract of ByteBuffer's superclass Buffer:
A buffer is a linear, finite sequence of elements of a specific primitive type. Aside from its content, the essential properties of a buffer are its capacity, limit, and position:
- A buffer's capacity is the number of elements it contains. The capacity of a buffer is never negative and never changes.
Therefore, if you were to allow "seamless dynamic growing", ByteBuffer would no longer act as a Buffer. This is also true regardless of interfaces versus abstract classes: Neither subclasses nor interface implementations should break invariants defined in the classes they extend. After all, consumers of your HypotheticalGrowingByteBuffer might rely on Buffer's fixed capacity to cache a single call to capacity()
, which otherwise would be defined not to change.
Another motivating factor behind making ByteBuffer an abstract class rather than an interface: The memory backing the buffer is defined to be necessarily fixed and contiguous, which allows for higher performance than a more flexible definition.
That said, Buffer defines a mutable concept of limit
, where a large originally-allocated buffer might have its availability artificially constrained. You can use this to constrain a large buffer to start small and then grow, though the growing will not be "seamless"; it will be limited by the original buffer capacity you define. If the goal is simply to concatenate smaller fixed-size buffers where the overall total size is predictable, it may be worthwhile to generate them as pieces of a larger buffer using ByteBuffer.duplicate and setting the mark and limit to constrain the writable area.