Arrays
The largest unit on the exam starts here. Fixed length, zero-indexed, and the two off-by-one errors that account for most lost marks.
By the end of this chapter you can
- Declare, create and initialise an array
- Traverse an array with both loop forms and know when each is usable
- Avoid ArrayIndexOutOfBoundsException at both ends
- Explain why an array parameter can be modified by a method
Unit 4 is 30–40% of the exam score — the largest single unit, and larger than Units 1 and 3 combined. It starts with arrays, and almost everything later in the unit is a loop over one.
Three ways to make one
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
// 1. Size only: every element gets a default value.
int[] a = new int[4];
// 2. Listed values, length inferred.
int[] b = {10, 20, 30};
// 3. Same, written out in full — needed when not on a declaration line.
int[] c = new int[]{7, 8};
System.out.println(Arrays.toString(a)); // defaults
System.out.println(Arrays.toString(b));
System.out.println(Arrays.toString(c));
System.out.println("lengths: " + a.length + " " + b.length + " " + c.length);
}
}The defaults are worth knowing because the exam tests them: 0 for numeric
types, false for boolean, and null for any object type — including
String, which is the one that surprises people.
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
int[] ints = new int[3];
boolean[] flags = new boolean[3];
String[] words = new String[3];
System.out.println(Arrays.toString(ints));
System.out.println(Arrays.toString(flags));
System.out.println(Arrays.toString(words));
// A String[] is full of nulls, not empty strings:
System.out.println("is it \"\"? " + "".equals(words[0]));
System.out.println("is it null? " + (words[0] == null));
}
}Calling a method on one of those nulls throws NullPointerException, and it is
a common way for an FRQ to fail at run time after looking complete.
length is a field, not a method
array.length // arrays — no parentheses
string.length() // Strings — parentheses
list.size() // ArrayList — different name entirelyThree collections, three spellings, and mixing them up is a compile error rather than a silent bug — which makes it annoying rather than dangerous. It still costs time on a written FRQ, where the compiler is not there to help.
Traversing
public class Main {
public static void main(String[] args) {
int[] scores = {88, 95, 72, 100};
// Indexed: you know where you are, and you can write.
int total = 0;
for (int i = 0; i < scores.length; i++) {
total += scores[i];
}
// Enhanced: shorter, read-only over the array itself.
int best = scores[0];
for (int s : scores) {
if (s > best) best = s;
}
System.out.println("total " + total + ", best " + best);
}
}Choose the indexed form when you need the position — to compare neighbours, to write into the array, or to start somewhere other than the beginning. Choose the enhanced form when you only need the values.
The two off-by-one errors
Valid indices run from 0 to length - 1. Both ends have a classic mistake.
public class Main {
public static void main(String[] args) {
int[] a = {1, 2, 3};
System.out.println("last is " + a[a.length - 1]);
System.out.println("about to go one too far…");
System.out.println(a[a.length]); // throws
}
}That sample is asserted to throw, and the verifier checks that it does — a demonstration of a crash that stopped crashing would be worse than useless.
The loop condition is the place this is decided:
i < a.length— correct.i <= a.length— one too far, and throws on the last iteration.
Arrays are objects
An array variable holds a reference. Two consequences that the exam tests directly:
import java.util.Arrays;
public class Main {
static void zeroFirst(int[] data) {
data[0] = 0; // reaches through the reference
}
static void reassign(int[] data) {
data = new int[]{99, 99}; // rebinds the local copy only
}
public static void main(String[] args) {
int[] nums = {5, 6, 7};
zeroFirst(nums);
System.out.println("after zeroFirst: " + Arrays.toString(nums));
reassign(nums);
System.out.println("after reassign: " + Arrays.toString(nums));
}
}The first method changes the caller’s array; the second does not. Java passes the reference by value — the method gets its own copy of the arrow, so it can follow the arrow and alter what is there, but pointing its copy somewhere else has no effect outside.
That single distinction explains every array-parameter question on the exam.