What does asReadOnlyBuffer() do, and when would you use it?
answer
- shares bytes, blocks writes (ReadOnlyBufferException)
- no copy; live view of the original's changes
- read-only != immutable (original owner can still write)
- independent position/limit/mark
- hasArray()/array() denied even for heap buffers
basics
~20 sasReadOnlyBuffer() returns a buffer that shares the same data but rejects any write (put throws). You use it to safely hand out a buffer's contents so callers can read but not modify the underlying bytes.
solid answer
~50 sasReadOnlyBuffer() creates a view over the same underlying storage as the original buffer, but marked read-only: isReadOnly() is true and any mutating call (put, compact, etc.) throws ReadOnlyBufferException. It does not copy the data — reads through the view see the live bytes, including changes the writable original makes afterward. It has its own independent position/limit/mark. The main use is encapsulation/defensive exposure: when an API exposes internal buffer data, returning a read-only view prevents callers from corrupting it without paying for a defensive copy. Note that read-only is enforced on the buffer object, not the memory — whoever holds the original writable buffer can still mutate the bytes, so it's protection against the recipient, not true immutability. A read-only buffer also reports hasArray() as false (it won't expose its backing array, even a heap one) to keep the bytes from being mutated through array().
code
java · 11 linesByteBuffer rw = ByteBuffer.allocate(4);
ByteBuffer ro = rw.asReadOnlyBuffer();
rw.putInt(0, 42); // writer mutates the shared bytes
System.out.println(ro.getInt(0)); // 42 - read-only view sees live changes
try {
ro.putInt(0, 99); // throws
} catch (java.nio.ReadOnlyBufferException e) {
System.out.println("cannot write through read-only view");
}go deeper
Knows asReadOnlyBuffer() gives a buffer you can read but not write, and that put throws.
Explains it shares storage (no copy), has independent cursors, and is used to expose data safely.
Distinguishes read-only from immutable (original owner can still mutate), notes array() denial, and chooses copy vs read-only view by requirement.
Frames it as a defensive-encapsulation tool in API design, weighing zero-copy read-only exposure against true-snapshot copies and the security implications of foreign-code access.
## The motivation: exposing data without giving away write access Suppose a class holds a `ByteBuffer` of internal state and a caller wants to read it. If you return the buffer directly, the caller can `put()` into it and corrupt your state. The two classic fixes are a **defensive copy** (safe but allocates and duplicates bytes) or a **read-only view** (no copy, but blocks writes). `asReadOnlyBuffer()` is the second option. ## What asReadOnlyBuffer() returns ```java ByteBuffer rw = ByteBuffer.allocate(16); ByteBuffer ro = rw.asReadOnlyBuffer(); ``` - `ro.isReadOnly()` is `true`. - Any mutating operation on `ro` — `put`, `putInt`, `compact`, etc. — throws `ReadOnlyBufferException` (an unchecked exception). - **No copy is made.** `ro` is a *view* over the **same** bytes as `rw`. If you write through `rw`, the new bytes are immediately visible when reading `ro`. - `ro` has its **own independent** position, limit, and mark (like any view). - `ro.hasArray()` is `false` and `ro.array()` throws, even when the underlying buffer is a heap buffer — because exposing the array would let the caller bypass read-only and mutate the bytes. ## Crucial subtlety: read-only ≠ immutable The read-only flag protects against **the holder of the read-only buffer**, not against everyone. Whoever still holds the original writable `rw` can change the bytes, and those changes show through `ro`. So `asReadOnlyBuffer()` gives you *"this recipient cannot write,"* not *"these bytes never change."* If you need a true snapshot, copy the bytes into a separate buffer instead. ## How it fits the view family Like `asIntBuffer()`/`duplicate()`/`slice()`, `asReadOnlyBuffer()` shares storage and has independent cursors. The difference is purely the write permission. (`duplicate()` is the writable equivalent that shares storage; `slice()` shares a sub-range.) A read-only buffer cannot be turned back into a writable one — there is no `asWritableBuffer()`; you'd have to copy into a fresh writable buffer. ## When to use it - **Defensive API surfaces:** return `internal.asReadOnlyBuffer()` from a getter to expose contents cheaply without risking mutation. - **Passing data to untrusted/foreign code** that should read but not modify. - **Documenting intent:** the type-level read-only flag makes "do not write" explicit and enforced, not just a comment. When you instead need guaranteed stability of the bytes over time (a true snapshot), prefer a copy. ## Pitfalls - Assuming read-only means the bytes are frozen — the original writer can still change them. - Expecting `array()` to work on a read-only heap buffer — it throws. - Forgetting that the read-only view still has its own position to manage when reading. ## Mental model `asReadOnlyBuffer()` is a *one-way mirror* onto the data: the recipient can look at the live contents but can't reach in and change them — though the person on the other side (the original buffer's owner) still can.
- Does asReadOnlyBuffer() guarantee the data won't change?No. It only stops the holder of the read-only view from writing. Whoever still holds the original writable buffer can mutate the shared bytes, and those changes are visible through the read-only view. For an unchanging snapshot you must copy the bytes into a separate buffer.
- Why does array() throw on a read-only heap buffer even though it has a backing array?Because handing back the array would let the caller mutate the bytes directly, defeating the read-only guarantee. So hasArray() returns false and array() throws ReadOnlyBufferException for any read-only buffer.
A one-way mirror: the viewer sees whatever is happening live on the other side but can't reach through to change it. The people behind the glass (holders of the writable buffer) can still rearrange the room.
saying these in an interview costs you the question
- Saying asReadOnlyBuffer() copies the data (it shares it).
- Claiming it makes the bytes immutable (the original writer can still change them).
- Expecting array() to work on a read-only heap buffer.
- Assuming you can convert it back to writable (you must copy instead).