What does ByteBuffer.wrap(array) do, and how does it differ from ByteBuffer.allocate()?
answer
- wrap = reuse existing array (no copy, aliased)
- allocate = brand-new zero-filled array
- wrap mutations leak to/from the array
- both are heap buffers (hasArray() true)
- wrap(arr, off, len) sets initial position/limit
basics
~20 swrap() does not create new storage — it makes a buffer that reuses an existing byte array, so changes through the buffer change that array. allocate() creates a brand-new array of the given size for the buffer.
solid answer
~50 sByteBuffer.allocate(n) creates a new heap buffer backed by a fresh, zero-filled byte[n] that only the buffer references. ByteBuffer.wrap(array) creates a heap buffer that shares the array you pass in — no copy is made, and the two are aliased: writing through the buffer mutates the original array and vice versa. wrap also sets position to 0 and limit to the array length (or the offset/length overload). You use wrap when you already have a byte[] (e.g. from a library or serialization) and want NIO operations on it without copying; you use allocate when you need new scratch space. Both produce heap buffers (hasArray() is true), so neither gives you a direct buffer. A subtle gotcha: because wrap shares state, later changes to the array are visible through the buffer, which can surprise callers if the array is mutated elsewhere.
code
java · 8 linesbyte[] data = {1, 2, 3, 4};
ByteBuffer wrapped = ByteBuffer.wrap(data); // shares data, no copy
wrapped.put(0, (byte) 99);
System.out.println(data[0]); // 99 <- the original array changed
ByteBuffer fresh = ByteBuffer.allocate(4); // new private byte[4]
fresh.put(0, (byte) 99);
// 'data' is untouched by 'fresh'go deeper
Knows wrap() reuses an existing array (no copy) while allocate() makes a new one; both are heap buffers.
Explains the aliasing consequence (mutations leak both ways) and when to copy instead, plus the wrap(arr, off, len) overload semantics.
Discusses isolation strategies, that capacity stays the full array length, and that neither produces a direct buffer.
Frames wrap vs allocate as an ownership/lifecycle decision in API design — avoiding shared-mutable-state bugs and unnecessary copies in hot paths.
## What problem these two methods solve Both `ByteBuffer.allocate(int)` and `ByteBuffer.wrap(byte[])` are **factory methods** that hand you a `ByteBuffer` — a position/limit/capacity wrapper around some bytes. They differ in **where those bytes come from**. ## Key term: aliasing *Aliasing* means two references point at the **same** underlying storage, so a change via one is visible via the other. This is the whole story here. ## allocate(n) ```java ByteBuffer buf = ByteBuffer.allocate(8); ``` - Allocates a **new** `byte[8]`, zero-filled, owned by the buffer. - Nothing outside the buffer references that array (unless you later call `buf.array()`). - `position = 0`, `limit = 8`, `capacity = 8`. - It is a **heap** buffer (backed by an on-heap array), so `buf.hasArray()` is `true`. Use it when you need fresh scratch space — e.g. a buffer to read a file into. ## wrap(array) ```java byte[] data = {1, 2, 3, 4}; ByteBuffer buf = ByteBuffer.wrap(data); ``` - Makes **no copy**. The buffer's backing array **is** `data` — they are **aliased**. - `position = 0`, `limit = data.length`, `capacity = data.length`. - Writing through the buffer (`buf.put(0, (byte) 99)`) changes `data[0]`, and changing `data` directly is visible through `buf`. - There is an overload `wrap(array, offset, length)` that additionally sets the initial position/limit to view a sub-range (but capacity is still the full array length). Use it when you already hold a `byte[]` — from deserialization, a network library, `String.getBytes()`, etc. — and want to run channel writes or NIO parsing on it without an extra copy. ## The crucial difference: ownership / sharing | | `allocate(n)` | `wrap(array)` | |---|---|---| | Storage | new `byte[n]` | the array you passed (shared) | | Copy made? | n/a (new) | **no** | | Mutations leak to/from outside | no (private) | **yes** (aliased) | | Buffer kind | heap | heap | Because `wrap` aliases, the common bug is assuming the buffer has its own private copy: if some other code mutates the array later, your buffer's contents change underneath you. If you need isolation, `allocate` then `put` the data, or copy the array first. ## What about direct buffers? Neither method gives a direct (off-heap) buffer — there is no `wrap` for native memory because there is no Java array to wrap. To get off-heap storage you must call `allocateDirect`. ## Quick mental model - `allocate` = *"give me new empty space."* - `wrap` = *"treat this array I already have as a buffer (and we now share it)."*
- If you want a buffer initialized from an existing array but isolated from later changes, what should you do?Don't wrap it. Either allocate(n) and put the bytes (buf.put(array) then flip), or copy the array (Arrays.copyOf) and wrap the copy. Both break the aliasing so external mutations of the original no longer affect your buffer.
- Can you wrap an array into a direct buffer?No. There is no wrap for native memory because a Java byte[] lives on the heap. Direct buffers come only from allocateDirect (or memory-mapped channels); to put array data into one you must copy via put.
allocate() buys a new blank notebook. wrap() puts a cover on a notebook you already own — write in it and the original pages change too, because it's the same notebook.
saying these in an interview costs you the question
- Saying wrap() copies the array — it shares it (aliases), no copy.
- Assuming the buffer from wrap() is isolated from later mutations of the array.
- Thinking wrap() can produce a direct buffer.
- Forgetting that wrap()'s capacity equals the full array length even with the offset/length overload.