Arrays: fixed-size lists
On This Lesson 11 topics
Lesson Overview
So far every variable you have used holds one value: one price, one name, one score. Real programs deal with many values of the same kind: the scores of thirty students, the temperatures of seven days, the prices on an invoice. Declaring score1, score2, score3 and so on does not scale, and you cannot loop over names that are different variables.
The tool for this is the array. Picture a row of numbered lockers. All lockers are the same size and hold the same kind of thing, the row has a fixed number of lockers decided when it is built, and the numbering starts at 0, not 1. You reach any locker directly by its number.
Why this matters: nearly every backend task handles lists of things, such as the rows returned by a query or the items in an order. The collections you will meet later (BEG-030) are built on this same idea, so a firm grip on arrays pays off for a long time.
This lesson builds on variables and types (BEG-009), loops (BEG-013), and methods (BEG-014).
Learning Objectives
By the end of this lesson you will be able to:
- Declare and create an array with
newand with an initializer list. - State the starting value of every element of a freshly created array.
- Read and write one element with an index, and read the size with
length. - Say which indices are valid for an array of a given length.
- Use a loop to process every element of an array.
- Explain why
b = adoes not copy an array, and why a method can change the array it receives. - Recognize an
ArrayIndexOutOfBoundsExceptionand read its message.
Written Explanation
An array is a row of lockers
An array is an object that holds a fixed number of values, all of the same type. Each value is an element, and each element has an index (its locker number). The Java Language Specification says arrays are 0-origin: an array of length n has indices 0 to n - 1.
int[] scores = new int[3]; // three int lockers: numbers 0, 1, 2Read the type int[] as "array of int". The array is an object, so, as with String in BEG-009, the variable scores holds a reference (a pointer) to it, not the lockers themselves.
Two ways to create an array
With new and a size. All elements start with the default value of their type: 0 for number types, false for boolean, and null for reference types such as String.
int[] scores = new int[3]; // {0, 0, 0}
boolean[] seen = new boolean[2]; // {false, false}
String[] names = new String[2]; // {null, null}With an initializer list. You write the values; the size is the number of values.
double[] prices = {9.5, 12.0, 3.25}; // length 3
String[] days = {"Mon", "Tue", "Wed"};The size is fixed once the array exists. There is no "add a fourth element". To get a different size you must create a new array and copy the values (a later lesson shows how).
Reading, writing, and length
Use square brackets with an index to read or write one element:
scores[0] = 95; // write locker 0
int first = scores[0]; // read locker 0The size is available as scores.length. Note that it is a field, so there are no parentheses. (String has a method length() with parentheses; do not mix the two up.)
The index can be any int expression: scores[i], scores[scores.length - 1]. The last valid index is always length - 1.
What happens with a bad index
Java checks every array access while the program runs. An index below 0 or greater than or equal to length throws an ArrayIndexOutOfBoundsException, and the program stops unless the error is handled. Java does not quietly read a neighbouring locker, as some other languages do, which makes bugs easier to find. The message tells you the bad index and the length, and the stack trace shows the line.
Processing every element
Because the indices are 0 to length - 1, the standard loop is:
for (int i = 0; i < scores.length; i++) {
// use scores[i]
}Start at 0, use < (not <=) against length. The next lesson studies this pattern more closely.
Arrays are references
Because the variable holds a pointer, two things follow from BEG-009 and BEG-014:
int[] b = a;copies the pointer, not the lockers. Both names now point at the same array, and a change through one is seen through the other.- When you pass an array to a method, the method receives a copy of the pointer. It cannot change which array your variable points at, but it can change the elements of the array both point at.
a ---+
+---> [ 50 | 60 | 70 ] b = a gives two names for ONE row
b ---+Examples
Example 1: create, read, write (simple)
public class Ex1 {
public static void main(String[] args) {
int[] scores = new int[3];
System.out.println(scores[0]);
scores[0] = 95;
scores[1] = 80;
scores[2] = 70;
System.out.println(scores[1]);
System.out.println(scores.length);
String[] names = new String[2];
System.out.println(names[0]);
double[] prices = {9.5, 12.0, 3.25};
System.out.println(prices[prices.length - 1]);
}
}Output (compiled and run with JDK 21):
0
80
3
null
3.25The new int array starts with zeros and the new String array with null. prices[prices.length - 1] is the idiom for "the last element".
Example 2: hottest day and average (practical)
public class Ex2 {
public static void main(String[] args) {
int[] temps = {18, 21, 19, 25, 23, 17, 20};
int hottest = temps[0];
int total = 0;
for (int i = 0; i < temps.length; i++) {
total += temps[i];
if (temps[i] > hottest) {
hottest = temps[i];
}
}
System.out.println("Hottest: " + hottest);
System.out.println("Average: " + (double) total / temps.length);
}
}Output:
Hottest: 25
Average: 20.428571428571427hottest starts at the first element, then the loop replaces it whenever it meets something bigger. Starting from 0 would be wrong if all values could be negative. The (double) cast avoids integer division (BEG-010).
Example 3: one array, two names, one method (realistic)
public class Ex3 {
static void curve(int[] marks, int bonus) {
for (int i = 0; i < marks.length; i++) {
marks[i] += bonus;
}
}
public static void main(String[] args) {
int[] marks = {50, 60, 70};
curve(marks, 5);
System.out.println(marks[0] + " " + marks[1] + " " + marks[2]);
int[] same = marks;
same[0] = 0;
System.out.println(marks[0]);
int[] bad = new int[3];
bad[3] = 1;
}
}Output (the last two lines are the error report):
55 65 75
0
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
at Ex3.main(Ex3.java:16)curve changed the caller's array because it received the same array. same[0] = 0 changed marks[0] for the same reason. The last statement asks for index 3 of a length-3 array. The message names the index (3), the length (3), and the line (16).
Backend Insight
Backend code constantly receives lists: the ids selected on a form, the lines of an uploaded file, the rows of a result. Arrays give you the simplest, fastest, most compact list, and many library structures are built on one inside. Two lessons from this one carry over directly:
- Sharing is cheap but dangerous. Passing an array to a method does not copy it. A method that changes its parameter changes the caller's data, which can cause bugs far from the cause. When you must protect the original, copy it.
- The fixed size is a real limit. If you do not know in advance how many items will arrive, a plain array is the wrong tool. That is why collections such as lists exist, and why you will learn them after arrays.
Common Mistakes
Mistake 1: Using index length
- Incorrect:
scores[scores.length] - Correct:
scores[scores.length - 1]for the last element.
Valid indices run from 0 to length - 1. An array of 5 has indices 0, 1, 2, 3, 4.
Mistake 2: Writing length() or size
- Incorrect:
scores.length() - Correct:
scores.length
On an array, length is a field with no parentheses. On a String it is the method length().
Mistake 3: Thinking b = a makes a copy
After b = a, there is one array and two names. Changing b[0] changes a[0]. A real copy comes in Lesson 6.
Mistake 4: Expecting the array to grow
Many beginners write a loop that "adds" results into an array and forget that the size was chosen at creation. Decide the size first, or use a different structure.
new int[3] has three lockers forever. Storing something at index 3 is an error, not an extension.
Mistake 5: Forgetting the default values
new String[2] holds null, not empty text. Calling a method such as names[0].length() on it throws a NullPointerException.
Exercises
Try each exercise yourself before opening the solutions.
Level A: Foundation
A1. Write two different ways to create an int array holding 3, 6, 9.
Show solution A1
A1. int[] a = {3, 6, 9}; and int[] b = new int[3]; b[0] = 3; b[1] = 6; b[2] = 9;.
A2. What are the starting contents of new boolean[2], new String[2], and new double[1]?
Show solution A2
A2. {false, false}, {null, null}, and {0.0}.
A3. For an array of length 6, list the valid indices. What happens with arr[6]?
Show solution A3
A3. Valid indices are 0, 1, 2, 3, 4, 5. arr[6] throws ArrayIndexOutOfBoundsException (index 6 out of bounds for length 6).
Level B: Application
B1. Given int[] a = {4, 8, 15, 16, 23, 42};, what are a.length, a[a.length - 1], and a[2] + a[3]?
Show solution B1
B1. a.length is 6, a[a.length - 1] is 42, and a[2] + a[3] is 15 + 16 = 31.
B2. Write the lines that swap the first and the last element of any int[] a with at least two elements.
Show solution B2
B2.
int tmp = a[0];
a[0] = a[a.length - 1];
a[a.length - 1] = tmp;The temporary variable keeps the first value safe while it is overwritten.
B3. Write a loop that counts how many elements of int[] a are greater than 10.
Show solution B3
B3.
int count = 0;
for (int i = 0; i < a.length; i++) {
if (a[i] > 10) {
count++;
}
}Level C: Challenge
C1. Predict the two numbers printed:
static void change(int[] a, int[] b) {
a[0] = 99;
b = new int[]{7, 7};
}
// in main:
int[] x = {1, 2};
int[] y = {3, 4};
change(x, y);
System.out.println(x[0] + " " + y[0]);Show solution C1
C1. It prints 99 3. a and x point at the same array, so a[0] = 99 changes x[0]. The line b = new int[]{7, 7} only moves the method's own copy of the pointer, so y still points at {3, 4}.
C2. Write a method static int find(int[] a, int target) that returns the index of the first element equal to target, or -1 when it is absent.
Show solution C2
C2.
static int find(int[] a, int target) {
for (int i = 0; i < a.length; i++) {
if (a[i] == target) {
return i;
}
}
return -1;
}Returning inside the loop stops at the first match. -1 is safe as "not found" because it is never a valid index.
Mini Challenge
Create an array of your own seven daily step counts (any numbers). Write a program that prints the lowest day's count, the index of that day, and the number of days above your average. Test it with a set where the lowest value is the first element and with one where it is the last, and check that neither run crashes.
Check your work: you used i < length, you started lowest from the first element, and the average is computed with a double.
Summary & Next Lesson
Key takeaways
- An array holds a fixed number of same-type elements, numbered from 0.
- Create it with
new int[n](default values) or with{...}. - Read and write with
a[i]; the size isa.length(no parentheses); the last index isa.length - 1. - A bad index throws
ArrayIndexOutOfBoundsException; the message gives the index and the length. - An array variable is a reference:
b = ashares one array, and a method can change the elements of an array it receives.
Next lesson
The next lesson, "Iterating and enhanced for", looks at the two ways to visit every element, when each fits, and how to keep every index in range.
Self-check
- What is the last valid index of an array of 5?
- What does
new int[4]contain? - Is it
a.lengthora.length()? - After
int[] b = a;, you setb[0] = 1. What happens toa[0]? - Can you add a fifth element to
new int[4]?
Show answers
- 4.
- Four zeros.
a.length, with no parentheses, for an array.a[0]is also 1, because both names point at one array.- No. The size is fixed; you must create a new, larger array.
References
- Oracle, Java Language Specification SE 21, chapter 10: Arrays. It supports: arrays are objects with a fixed
length, are 0-origin, accept initializer lists, set elements to default values on creation, and throwArrayIndexOutOfBoundsExceptionfor an index outside0tolength - 1. - The outputs and the error message above were produced by compiling and running the code with JDK 21. The locker picture is this course's own teaching device.
Practice
Apply this lesson with the module's lab, exercises and quiz.
Marking a lesson complete is optional and you can undo it any time. Your progress stays in this browser.