A record makes its component references final, but an array component remains mutable unless the record defines a defensive-copy policy.
Java records with arrays: copy on input and output
This complete program targets Java 17. Its displayed output is checked by the tutorial validation script.
Protect both directions
The batch record clones its incoming amounts array in the compact constructor. A caller then changes the original array without changing the record’s stored amount. The accessor also returns a clone, preventing a later caller from changing the record through the returned array.
Copying only in the constructor protects against the original reference but leaves the accessor as a mutation path. Copying only in the accessor leaves the caller’s original input reference connected to the stored array. Both directions are part of this ownership contract.
Equality needs its own decision
The fixture checks retained values and prints false when comparing two batches containing equal array values. The generated equality method treats an array component as an array object rather than promising element-by-element value equality for the batch. Decide whether that is appropriate before putting such records into sets or caches.
A clone of a primitive array copies its values. An object-array clone copies references, so nested mutable values need another policy. Equality contracts and Shallow ownership become relevant when replacing the amounts with richer business objects.
Working program
public class DefensiveReceiptBatch {
record Batch(int[] amounts) {
Batch {amounts=amounts.clone();}
public int[] amounts(){return amounts.clone();}
}
public static void main(String[] args) {
int[] input={125,75};Batch batch=new Batch(input);input[0]=0;
int[] output=batch.amounts();output[1]=0;
System.out.println(batch.amounts()[0]);System.out.println(batch.amounts()[1]);
System.out.println(batch.equals(new Batch(new int[]{125,75})));
}
}Output
125
75
falseCosts and boundaries
Construction and each accessor call take O(n) time and allocate an O(n) array. Repeated accessor calls inside a loop can turn one traversal into repeated copying. A scalar query or explicitly immutable representation may fit a large batch better.
Common Mistakes
- Final references do not make array contents immutable.
- Copy both entry and exit paths when that is the ownership contract.
- Do not assume generated array equality is element-wise.
Read next
Java records: value carriers and defensive copies, Java equals and hashCode: stable value keys, Spring API pagination: bounded requests and immutable snapshots.
