Passing Arrays to Methods
In 2-9 we discussed how pass-by-copy works with object references. You’ll recall that when we pass an object as an argument to a method, a copy of the reference to the object is passed, not a copy of the object itself. Therefore, since arrays are objects, when we pass an array into a method only a copy of the reference to the array is passed, not a copy of the entire array!
The end result is that both the calling code and the method will be referring to the same array in memory. If we change an element of the array in the method, it will have an effect on the array outside the current method call. Here’s an example demonstrating the difference between passing a primitive type and an array into a method.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
public class PassByCopy { public static void main( String[] args ) { int primitive = 7; int[] array = { 1, 2, 3, 4 }; System.out.println( "Before calling modifier():" ); System.out.println( "primitive = " + primitive ); System.out.print( "array contains: " ); for ( int i : array ) { System.out.print( i + " " ); } // Call modifier() method and pass primitive and array as arguments modifier( primitive, array ); System.out.println( "\n\nBack in main() after calling modifier():" ); System.out.println( "primitive = " + primitive ); System.out.print( "array contains: " ); for ( int i : array ) { System.out.print( i + " " ); } } // Method that modifies its primitive and array parameters public static void modifier( int primitive, int[] array ) { primitive = 99; array[0] += 1; array[1] -= 1; array[2] *= 2; array[3] /= 2; System.out.println( "\n\nInside modifier() parameters changed to:" ); System.out.println( "primitive = " + primitive ); System.out.print( "array contains: " ); for ( int i : array ) { System.out.print( i + " " ); } } } |
Before calling modifier():
primitive = 7
array contains: 1 2 3 4
Inside modifier() parameters changed to:
primitive = 99
array contains: 2 1 6 2
Back in main() after calling modifier():
primitive = 7
array contains: 2 1 6 2
Notice that the primitive variable remains unmodified in main() after the call to modifier(), but the elements of array remain changed. The fact that the local variables in main() and the parameter variables of modifier() have the same name makes no difference in this example, as you know they have different scopes.
Revisiting main()
I promised in 1-1 to fully explain this mysterious line we have been including in all of our programs. The time has come!
1 |
public static void main( String[] args ) |
We know that public means that the method can be called from outside the class, and that static means that main() can be called by the JVM without it having to create an instance of its class. Both of these features are important such that the JVM can automatically execute main() when we run our application. We also know that void means that main() does not return any value when it terminates.
What about String[] args? Now you can see that the args parameter is simply an array of String objects. But where would these strings come from? It turns out that if a Java application is run from the command line it’s possible to pass values called command line arguments to it. For example, if we run the following program:
1 2 3 4 5 6 7 8 9 |
public class CommandLineArgs { public static void main( String[] args ) { System.out.println( "Received these arguments from the command line:" ); for ( String arg : args ) { System.out.println( arg ); } } } |
from the Dr. Java interactions pane like this:
> java CommandLineArgs one 2 three
The result would be:
Received these arguments from the command line:
one
2
three
Like parameters to a method, command line arguments can be used to customize the behavior of the main() method if the program is run from the command line.
Variable Length Argument Lists
Imagine we’d like to be able to calculate the sum of a variety of double values:
1 2 3 4 5 6 7 8 9 10 11 12 |
public static void main( String args[] ) { double d1 = 1.0; double d2 = 3.2; double d3 = 5.4; double d4 = 6.6; System.out.printf( "Sum of d1 and d2 is %.1f\n", sum( d1 ) ); System.out.printf( "Sum of d1 and d2 is %.1f\n", sum( d1, d2 ) ); System.out.printf( "Sum of d1, d2 and d3 is %.1f\n", sum( d1, d2, d3 ) ); System.out.printf( "Sum of d1, d2, d3 and d4 is %.1f\n", sum( d1, d2, d3, d4 ) ); System.out.printf( "Sum of nothing is %.1f\n", sum() ); } |
Sum of d1 and d2 is 1.0
Sum of d1 and d2 is 4.2
Sum of d1, d2 and d3 is 9.6
Sum of d1, d2, d3 and d4 is 16.2
Sum of nothing is 0.0
So far all of the methods we have created have had a fixed number of parameters, so you might naturally assume that you would need to use method overloading to meet this requirement. Recall that method overloading is when you have two or more methods with the same name but different type, order, and/or quantity of parameters.
Rather than create five overloaded sum() methods, we can use a technique called variable length argument lists to solve this in a more elegant way.
1 2 3 4 5 6 7 |
public static double sum( double... numbers ) { double total = 0.0; for ( double d : numbers ) total += d; return total; } |
The double… part of the signature indicates that this method can accept zero (0) or more double arguments. When sum() receives its parameters it stores them in an array of doubles called numbers that can then be processed by the method. In this case we are using an enhanced for loop to calculate and return the total of the elements in the array.
Be careful when mixing a variable-length argument list with regular arguments. You may only include one variable-length argument list in a method signature, and it must appear at the end of the parameter list if you have other parameters defined.
The Arrays Class
The java.util package includes a class called Arrays (with an ‘s’) that includes a number of static methods that can be very handy when working with 1D arrays. Here’s a summary:
All of these methods are overloaded to handle arrays of any of the primitive types, and even arrays of objects such as Strings. Have a look at the Java API for complete details.
Here is a demonstration of these methods in action!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
import java.util.Arrays; public class HelpfulMethods { public static void main( String args[] ) { int[] numbers = new int[5]; // Display the contents of the array using the toString() method System.out.println("Initial numbers array: " + Arrays.toString( numbers ) ); // fill() the array Arrays.fill( numbers, 7 ); System.out.println("After fill(), numbers: " + Arrays.toString( numbers ) ); // Fill the array with random numbers between 0 and 9 for (int index = 0; index < numbers.length; index++ ) { numbers[index] = (int)(Math.random()*10); } System.out.println("Random fill, numbers: " + Arrays.toString( numbers ) ); // sort() the array Arrays.sort( numbers ); System.out.println("After sort(), numbers: " + Arrays.toString( numbers ) ); // binarySearch() the sorted array for the value 7 int foundIndex = Arrays.binarySearch( numbers, 7 ); System.out.println( "7 found at index " + foundIndex + " of numbers array (a negative index means NOT found). " ); // Compare to arrays for equality (i.e., same type, quantity, order, and value of elements) int[] newArray = { 1, 5, 2, 9, 7 }; if ( Arrays.equals( numbers, newArray ) == true ) { System.out.println( "numbers array is identical to newArray: " + Arrays.toString( newArray ) ); } else { System.out.println( "numbers array is different than newArray: " + Arrays.toString( newArray ) ); } // Create a new array containing the middle 3 elements from the numbers array newArray = Arrays.copyOfRange( numbers, 1, 4 ); System.out.println("After copying middle 3 elements from numbers to newArray: " + Arrays.toString( newArray ) ); } } |
Initial numbers array: [0, 0, 0, 0, 0]
After fill(), numbers: [7, 7, 7, 7, 7]
Random fill, numbers: [9, 3, 1, 7, 0]
After sort(), numbers: [0, 1, 3, 7, 9]
7 found at index 3 of numbers array (a negative index means NOT found).
numbers array is different than newArray: [1, 5, 2, 9, 7]
After copying middle 3 elements from numbers to newArray: [1, 3, 7]
At this point the code above should be easy for you to understand. In 3-1 we noted that the toString() method inherited from the Object class only displays the type and memory address of an array object, not its elements. As shown throughout the code above, the static Arrays.toString() method provides a handy solution.
Note that the array object passed to the binarySearch() method must be sorted for the method to produce meaningful results. Also, if there are duplicate elements in an array the binary search algorithm will find one of them, but it may not be the first one in the array. We’ll learn why this is so in 3-4.
You Try!
- Modify Q2 from 3-1 to take advantage of the sort(), binarySearch(), and toString() methods from the Arrays class. At the end, instead of displaying the friends in the order they were entered, display them in reverse alphabetical order.
- A common problem in Computer Science is eliminating duplicate data. Using input validation, prompt the user to enter 10 integers between 1 and 100 (inclusive). Use an array to keep track of the unique numbers entered. If they enter a number that has already been entered, do not add it to the array, and ask for another number. Once you have 10 unique numbers display them in sorted order.
- The main limitation of an array is that it has a fixed size. Sometimes we need to write code to deal with the situation where we need to increase the capacity of an array during run-time. Write an application that starts by defining an array called numbers for 5 integer elements. Using a conditional loop, prompt the user to enter a series of positive integers or -1 to quit. Store each positive int in the numbers array. If the numbers array reaches capacity your code should define a new int array object called newNumbers with 5 more elements than the numbers array. Next, copy all of the integers from the numbers array into the newNumbers array, then make numbers refer to the new, larger array object. In this way your code will be able to store any number of positive integers.
- Write an application that generates random sentences. Use four String arrays called article, noun, verb, and preposition. The article array should contain the articles “a”, “an”, “the”, “one”, and “some”; the noun array should contain nouns “dog”, “river”, “baby”, and “car”; the verb array should contain the verbs “ran”, “swam”, “cried”, “jumped”, “skipped”, and drove”; the preposition array should contain the prepositions “in”, “on”, “over”, “to”, and “from”. Create a sentence by selecting a word at random from each array in the following order: article, noun, verb, preposition, article, and noun. As each word is picked, concatenate it to the previous words in the sentence. The words should be separated by spaces. When the final sentence is output, it should start with a capital letter and end with a period. Your application should generate 3 random sentences and display them.