Arrays in depth
Object arrays, multidimensional arrays, the Arrays utility class, and varargs.
Arrays are the lowest-level container
A Java array is a fixed-size, homogeneous, first-class object that knows its own length (a.length, a field, not a method — and not length()). Once created its size never changes. Arrays are the fastest random-access container and the only one that holds primitives without boxing, but the trade-off is that you cannot grow or shrink them — that is exactly the gap the Collections framework fills.
### Arrays of objects hold references
When you write Event[] events = new Event[3]; you get an array of three slots, each initialised to null — no Event objects exist yet. The array reserves space for *references*, not for the objects themselves. You must fill the slots:
Event[] events = new Event[3]; // {null, null, null}
events[0] = new LightOn(200); // now slot 0 refers to a real Event
Contrast with int[] nums = new int[3];, which is {0, 0, 0} — primitive arrays are zero-filled, object arrays are null-filled. Reading events[1].action() before assigning slot 1 throws NullPointerException; reading nums[5] throws ArrayIndexOutOfBoundsException.
### Multidimensional arrays are arrays of arrays
int[][] grid = new int[2][3]; is really a length-2 array whose elements are each length-3 int[] arrays. Because each row is a separate object, rows can have different lengths (a *jagged* array): int[][] j = new int[2][]; j[0] = new int[]{1,2}; j[1] = new int[]{9};.
### The Arrays utility class
java.util.Arrays provides the static helpers you reach for constantly:
- Arrays.sort(a) — in-place sort (natural order, or supply a Comparator for object arrays).
- Arrays.fill(a, value) — set every element.
- Arrays.copyOf(a, newLen) — a resized copy (how ArrayList grows internally).
- Arrays.asList(x, y, z) — a fixed-size List view backed by the array.
- Arrays.toString(a) / Arrays.deepToString(a) — readable text (plain a.toString() prints a useless hash like [LEvent;@1b6d3586).
Worked example. Sort an array of String by length using a Comparator. Arrays.sort takes the array and a comparator; the comparator's compare(a, b) returns negative/zero/positive, and Integer.compare gives that safely without overflow:
String[] words = { "sort", "a", "list", "by", "length" };
Arrays.sort(words, (a, b) -> Integer.compare(a.length(), b.length()));
System.out.println(Arrays.toString(words));
// [a, by, sort, list, length] (stable: equal lengths keep input order)
### Varargs are arrays in disguise
A varargs parameter T... args is received by the method body as a T[]. Arrays.asList, String.format, and printf all use varargs. You may pass zero, one, or many arguments, or an existing array directly.