Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Java array copies: new slots can still point at old objects

Last updated: 1 Oct 20264 min read
tutorial
IntermediateBy AITrove Editorial

Arrays.copyOf creates a new array, but an object-array copy retains references to the same element objects.

Separate slot ownership from element ownership

Replacing a source array slot does not replace the corresponding copied slot. Mutating an object that both slots still reference is different: both arrays observe the object's new state. The fixture performs both changes so the two ownership boundaries are visible in the output.

The same shallow-copy issue appears when a record holds an array and when a LinkedList clone copies nodes but shares elements. Defensive record copies and LinkedList cloning cover those callers.

Choose a domain copy deliberately

If a caller must own a frozen snapshot of mutable shipments, create new immutable value objects or copy each mutable element under a defined constructor. A second array alone is insufficient. The exact copy depth depends on the object graph and alias policy; a generic recursive copy routine cannot infer which shared references are intentional.

Arrays.copyOf also pads a longer copy with null elements. Validate a requested length before allocating, and do not assume the extra slots contain usable records. Array bounds explains the index contract.

Working program

Java
import java.util.Arrays;

public class ShipmentArrayOwnership {
    static final class Shipment {
        String state;
        Shipment(String state) { this.state = state; }
    }
    public static void main(String[] args) {
        Shipment sharedShipment = new Shipment("queued");
        Shipment[] live = {sharedShipment};
        Shipment[] snapshotSlots = Arrays.copyOf(live, live.length);
        live[0] = new Shipment("manual-review");
        System.out.println(snapshotSlots[0].state);
        sharedShipment.state = "sent";
        System.out.println(snapshotSlots[0].state);
        System.out.println(live[0].state);
    }
}

Output

Output
queued
sent
manual-review

Cost and ownership

Copying n references takes O(n) time and O(n) additional slots. It does not allocate n new Shipment objects. A deeper copy has extra allocation and must state how nested references, cycles, and shared identities are handled.

Common Mistakes

  • Do not call an object-array copy an immutable snapshot of its elements.
  • Do not assume a longer copy has initialized domain values in padded slots.
  • Do not expose a caller-owned array from a supposedly immutable object.

Read next

Java arrays and bounds, Java records with arrays: copy on input and output, Java LinkedList clone: copied nodes, shared element objects, Java pass-by-value: references and mutation.

java
array-copy-ownership
Storage details