Concepts / Subroutine Parameters and Arguments

Subroutine Parameters and Arguments

A parameter may have an array type such as int[], so one argument can deliver an entire array to a subroutine.

  • Programming

A Printing Task That Needs a Whole List

Suppose you want a subroutine that prints every value in an integer array in a tidy format: the values separated by commas and enclosed in square brackets. The subroutine has to know which array to print, and the Java way to supply that information is through a parameter. This article looks at what happens when the type of a parameter is itself an array type, so that a whole collection of values travels into the subroutine as one argument.

What do you think happens?

A caller creates an integer array holding the values 42, 17 and 256, then calls the list-printing subroutine on it. What text appears on the screen, including where the brackets and commas fall?

Reveal answer
Answer:

[42, 17, 256]

The brackets and commas are not produced by the array itself. They come from explicit print statements in the subroutine's loop, so their placement has to be traced pass by pass. The program later in this article produces exactly this line.

Declaring an Array Parameter

Definition

A parameter's type is normally a simple type such as int, but it can also be an array type. Writing int[] as the parameter type means the subroutine accepts an integer array. The name after the type, here list, is the name the subroutine uses for the array inside its own body.

java
Notes on the code
  • int[] means the parameter is an array of integers, not a single int
  • list is the name used for that array inside the subroutine body

Read the header from left to right: the word void says the subroutine returns no value, the name printValuesInList identifies the subroutine, and the text inside the parentheses declares one parameter. That parameter has the type int[] and the name list. The brackets after int are what make it an array parameter. Without them, the parameter would accept only one int.

Creating the Array in Calling Code

A subroutine cannot be called with an array that does not exist yet. The array must be created and initialized first, and only then can it be passed as the argument. The source illustrates this with a short segment that declares an array variable, creates an array of three integers, fills in its elements and then makes the call. The source itself calls this a legal but not very realistic piece of code, since the array exists only to be handed to the subroutine.

java
Notes on the code
  • new int[3] creates an array with room for three integers
  • the three assignments fill positions 0, 1 and 2
  • the call passes the whole array using the single name numbers

Passing the Array as One Argument

When the call printValuesInList( numbers ) runs, the name numbers appears in the argument position, and the subroutine receives the array as its list parameter. The subroutine does not need to know the name numbers. It works with the array it was given through list, and every reference to list inside the body refers to that array. Only one argument crosses the call, even though the array holds three values.

numbersname in the calling codelistparameter name in thesubroutineint array of 3 valuesone shared array objectrefers torefers to the same array
When the subroutine changes an element of its int[] parameter, does the caller's array change too, and what exactly is shared between the two?

The diagram shows what is shared. The caller's name numbers and the subroutine's parameter name list are two different names, but both lead to the same array. The subroutine receives that array itself as its argument, which is why the array is the thing that travels across the call, not a copy of its three values listed one by one.

Reading Elements with Index and Length

Inside the subroutine, an element is reached by writing the array name followed by an index in square brackets, as in list[i]. The index says which position to read. Positions in Java arrays are numbered starting from zero, so the first value is at index 0 and the last value is at index 2 in a three-element array. The subroutine also needs to know how many positions exist, so it uses the length property of the array. Together these two ideas form the loop that prints the values one at a time.

list[0]42list[1]17list[2]256next positionnext position
Which storage position does each index refer to, and why does a loop that uses length stop at the last valid index rather than at length?

The length of a three-element array is 3, but the valid indexes are 0, 1 and 2. That is why the loop condition is written as i < list.length rather than i <= list.length. A loop that runs while i is less than the length visits every valid position once and then stops. The loop never names the values 42, 17 or 256. It reads the length and the elements from whatever array it receives, so the same subroutine works for any array of integers.

Tracing the Printing Loop

java
Output
[42, 17, 256]
Walk through it
  1. 1
    main creates an array of three integers and fills positions 0, 1 and 2
  2. 2
    main calls printValuesInList with numbers, so list refers to that same array
  3. 3
    the opening bracket is printed before the loop starts
  4. 4
    when i is 0, list[0] (42) is printed and a comma follows because 0 is less than 2
  5. 5
    when i is 1, list[1] (17) is printed and a comma follows because 1 is less than 2
  6. 6
    when i is 2, list[2] (256) is printed and no comma follows because 2 is not less than 2
  7. 7
    the loop stops because i reaches 3, which is not less than list.length
  8. 8
    the closing bracket is printed and the subroutine returns to main
Notes on the code
  • the opening bracket is printed once, before the loop
  • each pass prints one element using list[i]
  • the comma is printed only when i is not the last index
i = 0prints 42 then commai = 1prints 17 then commai = 2prints 256, no commai = 3loop ends, prints ]i++i++i++
On each iteration, which element is read and what is printed, and at which step does the printed output first depart from what the learner expected?

Trace the output one pass at a time. The first pass prints the opening bracket, then 42 and a comma. The second pass prints 17 and a comma. The third pass prints 256 with no comma, because the comma test fails at the last index. Finally the closing bracket is printed. Combined, the screen shows [42, 17, 256]. The brackets and commas are produced by the explicit print statements in the loop, not by the array, which is exactly why their placement has to be traced.

Mistakes When Passing Arrays

  • Common mistake

    Declaring the parameter as a single int when the subroutine needs the whole array

    What it looks like
    public static void printValuesInList(int list)
    Why it fails

    The brackets are what declare an array parameter. Without them, the parameter accepts only one integer, not a collection of values.

    Do this instead

    Write int[] list so the parameter type is an integer array.

  • Common mistake

    Calling the subroutine before the array has been created and filled

    What it looks like
    int[] numbers; printValuesInList( numbers );
    Why it fails

    A subroutine cannot be called with an array that does not exist yet, so the array must be created and initialized first.

    Do this instead

    Create the array with new, fill its positions, and only then make the call.

  • Common mistake

    Looping with i <= list.length

    Why it fails

    The valid indexes stop one short of the length, so an index equal to the length refers to no position in the array.

    Do this instead

    Use i < list.length so the loop visits each valid index once.

  • Common mistake

    Expecting the printed commas to come from the array

    Why it fails

    The commas and brackets are produced by explicit code in the loop, so removing the comma test changes the printed text without changing the data.

    Do this instead

    Trace the printing code pass by pass to predict where each comma and bracket appears.

A useful debugging habit follows the order the source recommends. When a subroutine that takes an array prints something unexpected, first check the call: was the array created and filled before the call? Next check the parameter type. Then follow the loop one pass at a time, watching the index, the length check and the comma test. Most surprises in this subroutine come from one of these places, so tracing them in order narrows the search quickly.

Practice: Predicting Printed Output

MEDIUM

Using the printValuesInList subroutine above, a caller creates an array with the values 5, 5 and 9 in positions 0, 1 and 2, then calls printValuesInList on it. Write the exact text that appears on the screen, including every bracket and comma. Then identify the first pass in which your prediction could differ from what a careless reading would expect.

Hints
  • Count the valid indexes first: the length is 3, so the loop visits indexes 0, 1 and 2.
  • The opening bracket is printed once before the loop, and the closing bracket once after it.
  • A comma is printed only on passes where the index is less than the last index.

Key Takeaways

  • A parameter declared as int[] lets one argument deliver an entire integer array to a subroutine.
  • The array must be created and initialized in the calling code before it is passed, and the call passes one argument that refers to that array.
  • Inside the subroutine, list[i] reads the element at index i, indexes start at zero, and the loop condition i < list.length visits every valid position.
  • The brackets and commas in printed output come from explicit code in the loop, so they must be traced pass by pass to predict the exact output.