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.
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
[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
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.
- 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.
- 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.
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.
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
[42, 17, 256]- 1main creates an array of three integers and fills positions 0, 1 and 2
- 2main calls
printValuesInListwith numbers, so list refers to that same array - 3the opening bracket is printed before the loop starts
- 4when i is 0, list[0] (42) is printed and a comma follows because 0 is less than 2
- 5when i is 1, list[1] (17) is printed and a comma follows because 1 is less than 2
- 6when i is 2, list[2] (256) is printed and no comma follows because 2 is not less than 2
- 7the loop stops because i reaches 3, which is not less than
list.length - 8the closing bracket is printed and the subroutine returns to main
- 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
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 likepublic static void printValuesInList(int list)Why it failsThe brackets are what declare an array parameter. Without them, the parameter accepts only one integer, not a collection of values.
Do this insteadWrite 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 likeint[] numbers; printValuesInList( numbers );Why it failsA subroutine cannot be called with an array that does not exist yet, so the array must be created and initialized first.
Do this insteadCreate the array with new, fill its positions, and only then make the call.
Common mistake Looping with i <= list.length
Why it failsThe valid indexes stop one short of the length, so an index equal to the length refers to no position in the array.
Do this insteadUse i < list.length so the loop visits each valid index once.
Common mistake Expecting the printed commas to come from the array
Why it failsThe 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 insteadTrace 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
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.lengthvisits 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.