Defensive copying, and why returning internal mutable state directly is a real bug
Returning a reference to internal mutable state (an array, a List, a Date) directly hands the caller the
power to corrupt your object's internal invariants from outside -- often by complete accident. The fix costs
almost nothing: return a copy instead. .clone() on arrays does exactly this and is one of the few places
clone() is genuinely the idiomatic choice rather than a copy constructor.
class LeakyBox {
private int[] data = {1, 2, 3};
int[] getData() { return data; } // hands out the ACTUAL internal array
}
class SafeBox {
private int[] data = {1, 2, 3};
int[] getData() { return data.clone(); } // hands out an independent copy
}
LeakyBox leaky = new LeakyBox();
int[] leakedRef = leaky.getData();
leakedRef[0] = 999; // "just modifying my local copy"... except it wasn't a copy
System.out.println("LeakyBox's internal state got corrupted from outside: " + java.util.Arrays.toString(leaky.getData()));
SafeBox safe = new SafeBox();
int[] copy = safe.getData();
copy[0] = 999;
System.out.println("SafeBox's internal state is untouched: " + java.util.Arrays.toString(safe.getData()));