Skip to content
Ameen Abozaid
PublishedBEG-015-L01

Arrays: fixed-size lists

  • Lesson 1 of 8
  • 10 min read
  • Beginner
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 new and 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 = a does not copy an array, and why a method can change the array it receives.
  • Recognize an ArrayIndexOutOfBoundsException and 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.

java
int[] scores = new int[3];   // three int lockers: numbers 0, 1, 2

Read 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.

java
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.

java
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:

java
scores[0] = 95;                 // write locker 0
int first = scores[0];          // read locker 0

The 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:

java
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.
text
  a ---+
       +--->  [ 50 | 60 | 70 ]     b = a  gives two names for ONE row
  b ---+

Examples

Example 1: create, read, write (simple)

java
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):

text
0
80
3
null
3.25

The 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)

java
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:

text
Hottest: 25
Average: 20.428571428571427

hottest 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)

java
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):

text
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.

java
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.

java
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:

java
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.

java
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 is a.length (no parentheses); the last index is a.length - 1.
  • A bad index throws ArrayIndexOutOfBoundsException; the message gives the index and the length.
  • An array variable is a reference: b = a shares 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

  1. What is the last valid index of an array of 5?
  2. What does new int[4] contain?
  3. Is it a.length or a.length()?
  4. After int[] b = a;, you set b[0] = 1. What happens to a[0]?
  5. Can you add a fifth element to new int[4]?
Show answers
  1. 4.
  2. Four zeros.
  3. a.length, with no parentheses, for an array.
  4. a[0] is also 1, because both names point at one array.
  5. 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 throw ArrayIndexOutOfBoundsException for an index outside 0 to length - 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.

Lab and exercises Quiz

Marking a lesson complete is optional and you can undo it any time. Your progress stays in this browser.

Continue to next lesson

Type to search levels, phases, modules and lessons.