How does Arrays.copyOf relate to System.arraycopy, and when would you use each?
answer
- copyOf = new array + arraycopy internally
- copies min(original.length, newLength)
- grow → tail filled with defaults; shrink → truncated
- copyOfRange uses 'to' exclusive
- arraycopy needs an existing dest; copyOf allocates
basics
~20 sArrays.copyOf allocates a brand-new array of the size you ask for and uses System.arraycopy internally to fill it. Use copyOf when you want a fresh array; use arraycopy when you already have the destination and want to copy into a specific spot.
solid answer
~40 sArrays.copyOf(original, newLength) creates a new array of length newLength and then calls System.arraycopy to copy min(original.length, newLength) elements into it; if newLength is larger, the tail is left at the default value (0, false, or null), and if smaller, the array is truncated. So copyOf is a convenience built on top of arraycopy that handles allocation and right-sizing for you. Arrays.copyOfRange(arr, from, to) is similar but copies a sub-range. Reach for copyOf/copyOfRange when you want a new array of a chosen size — it is clearer and less error-prone. Reach for System.arraycopy directly when the destination already exists, when copying into the middle of an array, when shifting elements within one array (insert/remove), or when you must avoid the extra allocation.
go deeper
Knows Arrays.copyOf makes a new array and that arraycopy copies into an existing one.
Explains copyOf is built on arraycopy, copies min(lengths), pads with defaults when growing, truncates when shrinking, and can pick between them by intent.
Articulates the allocation tradeoff, the copyOfRange exclusive-bound semantics, and chooses arraycopy for in-place shifts or buffer reuse to cut GC.
Reasons about allocation/zeroing cost in hot paths, escape analysis, and library design — why the JDK exposes both a raw primitive and convenience wrappers.
## The relationship `System.arraycopy` is a **primitive**: it copies a range from an existing source array into an existing destination array. It does **not** allocate anything. `Arrays.copyOf` is a **convenience method** layered on top of it that *does* allocate. A simplified version of `Arrays.copyOf` looks like: ```java public static int[] copyOf(int[] original, int newLength) { int[] copy = new int[newLength]; // allocate the new array System.arraycopy(original, 0, copy, 0, // fill it using the primitive Math.min(original.length, newLength)); return copy; } ``` So `copyOf` does three things `arraycopy` does not: (1) it **creates** the destination array, (2) it **chooses the count** as `min(original.length, newLength)` so it never over-reads, and (3) it **returns** the new array. ## Resizing semantics of copyOf - If `newLength > original.length`, the extra trailing slots get the type's **default value**: `0` for numeric primitives, `false` for `boolean`, `''` for `char`, and `null` for reference types. This is how you "grow" an array. - If `newLength < original.length`, the result is **truncated** to the first `newLength` elements. - If `newLength == original.length`, you get a full, independent copy (a clone). ## copyOfRange `Arrays.copyOfRange(arr, from, to)` returns a new array containing `arr[from .. to-1]` (`to` is exclusive). It too is implemented with `System.arraycopy`. It can read past `arr.length` if `to` exceeds it — those positions are filled with defaults, just like the grow case. ## When to use which **Use `Arrays.copyOf` / `copyOfRange` when:** - You want a *new*, correctly-sized array (clone, grow, shrink, slice). - Clarity matters more than micro-control — there are no index-math mistakes to make. **Use `System.arraycopy` directly when:** - The destination already exists and you want to copy into a specific offset. - You are shifting elements *within* a single array (e.g. inserting or removing in a list-like structure, where `src == dest`). - You want to avoid the allocation that `copyOf` performs (e.g. reusing a pooled buffer). ## Performance note Because `copyOf` simply wraps `arraycopy`, the copy itself is the same fast block move. The only added cost is allocating (and zero-initializing) the new array. So `copyOf` is essentially "arraycopy + an allocation"; if you already have a buffer, going straight to `arraycopy` avoids that allocation.
- If you call Arrays.copyOf with a newLength larger than the original, what is in the extra slots?The type's default value: 0 for numeric primitives, false for boolean, '' for char, and null for reference (object) arrays. The first original.length slots hold the copied values.
- Why might you prefer System.arraycopy over Arrays.copyOf in a hot loop?To avoid the per-call allocation and zero-initialization of a new array. If you can reuse an existing destination buffer, arraycopy does only the copy, which reduces GC pressure and allocation cost.
saying these in an interview costs you the question
- Saying copyOf and arraycopy are interchangeable — copyOf allocates and returns, arraycopy does not
- Thinking copyOf throws when newLength exceeds the original (it pads with defaults instead)
- Believing copyOfRange's 'to' index is inclusive
- Assuming arraycopy can grow an array — it cannot allocate