W3docs

Copying Arrays in Java

Copy Java arrays with System.arraycopy, Arrays.copyOf, clone, and stream- based copying.

Assigning one array variable to another doesn't copy anything — it just makes two names point at the same underlying array:

int[] a = {1, 2, 3};
int[] b = a;
b[0] = 99;
System.out.println(a[0]);   // 99 — same array

To get an independent copy you have to ask for one explicitly. Java offers several ways, each suited to a different situation: full duplicate, resize while copying, slice, copy between two existing arrays.

Arrays.copyOf — duplicate or resize

Takes the source and a target length. If the new length matches, you get a clean copy. If it's larger, the extra slots are filled with default values (0, false, null); if it's smaller, the tail is dropped.

import java.util.Arrays;

int[] data = {1, 2, 3, 4, 5};
int[] same   = Arrays.copyOf(data, data.length);   // {1, 2, 3, 4, 5}
int[] grown  = Arrays.copyOf(data, 8);             // {1, 2, 3, 4, 5, 0, 0, 0}
int[] shrunk = Arrays.copyOf(data, 3);             // {1, 2, 3}

This is how you "grow" an immutable-size array — allocate a bigger one and copy.

Arrays.copyOfRange — slice

Copies a half-open range [from, to):

int[] data = {1, 2, 3, 4, 5};
int[] middle = Arrays.copyOfRange(data, 1, 4);   // {2, 3, 4}

to is allowed to exceed the source length — extra slots come back as defaults. So you can slice and pad in one call.

System.arraycopy — copy into an existing array

The lowest-level primitive: copy a range of one array into a range of another. No new allocation, no return value — both arrays must already exist.

int[] src = {10, 20, 30, 40, 50};
int[] dst = new int[8];
System.arraycopy(src, 1, dst, 3, 3);
// dst is now {0, 0, 0, 20, 30, 40, 0, 0}

The arguments are (src, srcStart, dst, dstStart, length). Use this when you want to place data at a specific offset, or when you're moving elements around inside the same array — System.arraycopy(arr, i, arr, i + 1, length - i - 1) shifts a slice right by one to make room for an insert. Overlapping ranges within a single array are supported and handled correctly.

clone() — quick full copy

Every array has a clone() method that returns a new array of the same length and contents:

int[] data = {1, 2, 3};
int[] copy = data.clone();

For one-dimensional arrays, clone() is the shortest, clearest way to duplicate. The return type is the same as the source — no cast needed.

For multi-dimensional arrays, clone() is shallow: it copies the outer array, but the rows are still the original references:

int[][] grid = {{1, 2}, {3, 4}};
int[][] shallow = grid.clone();
shallow[0][0] = 99;
System.out.println(grid[0][0]);   // 99 — same inner row

To deep-copy a 2D array, clone each row in turn:

int[][] deep = new int[grid.length][];
for (int r = 0; r < grid.length; r++) deep[r] = grid[r].clone();

A stream version: Arrays.stream(grid).map(int[]::clone).toArray(int[][]::new).

Streams

For object arrays, Arrays.stream(arr).toArray(T[]::new) produces a copy:

String[] names = {"Ada", "Linus", "Grace"};
String[] copy = Arrays.stream(names).toArray(String[]::new);

For primitive arrays, use the specialized stream:

import java.util.stream.IntStream;

int[] data = {1, 2, 3, 4, 5};
int[] copy = IntStream.of(data).toArray();

Streams are heavier than copyOf or clone() and exist mainly for the transform case — .map(...) or .filter(...) mid-pipeline — not for plain duplication.

Reference vs. deep copies

For primitives, every copy is fully independent — the values themselves get duplicated. For object arrays, all the copy methods we've covered are shallow: they duplicate the array of references, but every reference still points at the same object as the original.

StringBuilder[] src = { new StringBuilder("hi") };
StringBuilder[] copy = src.clone();
copy[0].append(" there");
System.out.println(src[0]);   // "hi there" — same StringBuilder

That's usually fine — Strings, Integers, and anything immutable can be shared safely. If the elements are mutable and you need independent objects, you have to copy them yourself:

StringBuilder[] deep = new StringBuilder[src.length];
for (int i = 0; i < src.length; i++) deep[i] = new StringBuilder(src[i]);

Picking a copy method

You wantUse
Exact duplicate of a 1D arrayarr.clone() or Arrays.copyOf(arr, arr.length)
Resize while copying (grow/shrink)Arrays.copyOf(arr, newLength)
Slice — copy part of an arrayArrays.copyOfRange(arr, from, to)
Copy into a slot in an existing arraySystem.arraycopy(...)
Deep-copy a 2D arrayclone each row in a loop
Copy and transformstreams (map, filter, then toArray)

A worked example

java— editable, runs on the server

What's next

You can now create, walk, search, sort, and copy arrays — the full toolkit for working with Java's fixed-size containers. Up next is the part on methods: how to package code into named, reusable units that take parameters and return values.

Practice

Practice

What does arr.clone() return for an int[][]?