Start learning free

LESSON 101 OF 414 · ARRAYS I

Exceeding Static Array Bounds in Scala: Fixing the Index Error

Lesson Read the full explanation

When accessing array data with indices, the most common problem we can run into is exceeding the array's bounds.

Remember, the items of an array are indexed from 0 to length - 1. Any index which is not in this range is invalid.

When you try to access an item with an invalid index, Scala throws an exception:

val ourArray = Array(50, 40, 30)

// Valid indices: 0, 1, 2
println(ourArray(0)) // Output: 50
println(ourArray(2)) // Output: 30

// Invalid indices: 3, 30, -1
println(ourArray(3)) // throws ArrayIndexOutOfBoundsException
println(ourArray(30)) // throws ArrayIndexOutOfBoundsException
println(ourArray(-1)) // throws ArrayIndexOutOfBoundsException

As programmers, we always want to make sure that we don't exceed one array's bounds in our programs.


Assignment
Follow the Coding Tutorial and let's play with some arrays.


Hint
Look at the examples above if you get stuck.


STEP 1 OF 1
    Ctrl + Enter to check

    SCALA · ARRAYS I

    Exceeding Static Array Bounds in Scala, explained

    Valid and invalid indexes

    An array with length elements has valid indexes from 0 to length - 1. Any other index is invalid. Using one doesn't produce a wrong value or a silent default. The program throws an exception:

    val ourArray = Array(50, 40, 30)
    // Valid indices: 0, 1, 2
    println(ourArray(0)) // 50
    println(ourArray(2)) // 30
    // Invalid indices: 3, 30, -1
    println(ourArray(3))  // throws ArrayIndexOutOfBoundsException
    println(ourArray(30)) // throws ArrayIndexOutOfBoundsException
    println(ourArray(-1)) // throws ArrayIndexOutOfBoundsException
    

    The exception is thrown while the program runs, and the compiler does not warn about it. Its message names the index and the length. For the array of four ages below, index 4 gives Index 4 out of bounds for length 4, and index -1 gives Index -1 out of bounds for length 4. When an exception isn't caught, it ends the program, and any lines after it never run.

    The buggy code

    The lesson wants to print the last element of ages:

    val ages = Array(14, 32, 50, 21)
    println(ages(ages.length))
    

    It throws ArrayIndexOutOfBoundsException instead of printing 21. The expression ages.length is 4, the number of elements. But the four elements sit at indexes 0, 1, 2 and 3, so index 4 is one position past the end.

    The fix

    1. Find the index the code uses. It is ages.length, which is 4.
    2. Find the index the code needs. The last element of a four-element array is at index 3, which is length - 1.
    3. Subtract 1. Change the index to ages.length - 1.
    val ages = Array(14, 32, 50, 21)
    println(ages(ages.length - 1))
    

    This prints 21. It also keeps working if you change the array to hold more or fewer numbers, which a hard-coded ages(3) would not.

    Avoiding the error in general

    • Loop up to the length, not through it. for (i <- 0 until ages.length) stops at the last valid index. 0 to ages.length includes the length and fails on the last pass.
    • Check before reading. When an index comes from elsewhere, test i >= 0 && i < ages.length first.
    • Ask for an Option. ages.lift(4) returns None for an invalid index, and Some(value) for a valid one. ages.lift(4).getOrElse(0) gives 0 here, without an exception.
    • Catch the exception with try / catch when failing is acceptable, as in case e: ArrayIndexOutOfBoundsException => .... Checking the index first is usually the better choice, since an out-of-range index normally means the code has a bug.

    Common mistakes

    • Treating length as the last index. This is the bug in the lesson, and it is the most common form of the error.
    • Counting from 1. The third element is at index 2. Asking for index 3 in a three-element array fails.
    • Empty arrays. For an empty array, length - 1 is -1, and reading index -1 throws as well. Index -1 does not mean "the last element" in Scala, unlike in some other languages.
    • Writing past the end. Assigning to an invalid index, such as ages(4) = 1, throws the same exception. A fixed-size array can't grow.

    Reading the stack trace

    When the exception ends the program, the message starts with the exception's name, followed by the details. Compare the two numbers in Index 4 out of bounds for length 4. If the index equals the length, you are one past the end, which usually means a missing - 1. If the index is negative, a subtraction went too far, often from an empty array. Reading those two numbers first usually shows the cause faster than rereading the whole program.

    Key takeaways

    • Valid indexes are 0 to length - 1.
    • An invalid index throws ArrayIndexOutOfBoundsException at run time.
    • The last element is array(array.length - 1).
    Keep going with ScalaAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free