Arrays and References
An Introduction with Examples in Java |
Prof. David Bernstein |
Computer Science Department |
bernstdh@jmu.edu |
new
operator is used to allocate memory
for arraysnew
operator returns a referenceWe can now look more closely at what happens when an array is declared and when it is instantiated.
// Allocate four bytes to hold the address of the array // when it is created. Add scores to the name table. // int[] scores; // Allocate (from the heap) enough memory to hold // 5 int-values (20 bytes in total), initialize // each element to 0, and assign 5 to the // final attribute named length (at that address). // // Then, store the address in the four bytes // named scores. // scores = new int[5];
[ ]
Operator// Assign the value 10 to the memory location // at the address of scores plus the size of 1 int-value // (i.e., scores plus 4) // scores[1] = 10; // Retrieve the value located in the memory location // at the address scores plus 4 bytes and print it // (i.e., print the value 10) // System.out.printf("%d\n", scores[1]);
String[] aka, original; original = new String[3]; original[0] = "Federal Bureau of Investigation"; original[1] = "Central Intelligence Agency"; original[2] = "Department of Transportation"; aka = original; // aka and original contain the same reference // (i.e., are aliases) aka[0] = "FBI"; // This will print "FBI" // System.out.println(original[0]);
An array of objects is really an array of references.
// Allocate four bytes to hold the address of the array // when it is created. Add identity to the name table. // Color[] identity; // Allocate enough memory to hold 2 addresses (8 bytes in total), // initialize each element to null, assign to to the (final) attribute // named length (at that address), and store the address of the // array in the four bytes named identity. // identity = new Color[2]; // Allocate memory to hold each Color, initialize // the attributes of the objects, and put the address // in the appropriate element in the array. // identity[0] = new Color( 69, 0, 132); identity[1] = new Color(173, 156, 101);
final
The fact that arrays are reference types leads to some "surprises"
about arrays that are declared to be final
.
Specifically, a reference can only be assigned to the array once,
but values/references can be assigned to the elements of the array
multiple times.
final int[] range; range = new int[2]; range[0] = 0; range[1] = 100; // These lines will compile range[0] = -1000; range[1] = 1000; // This line will not compile range = new int[2];
The relational equals operator (i.e., ==
) compares
references. To compare elements, use the
array's .equals()
method or
the Arrays.equals()
method, but be careful since they rely on
the elements .equals()
method which may not do what you want.
int[] a, b, c; a = new int[2]; b = new int[2]; a[0] = 10; a[1] = 100; b[0] = 10; b[1] = 100; c = a; if (a == b) System.out.println("a and b are aliases"); if (a == c) System.out.println("a and c are aliases"); if (b == c) System.out.println("b and c are aliases"); if (a.equals(b)) System.out.println("a.equals(b) is true"); if (a.equals(c)) System.out.println("a.equals(c) is true"); if (b.equals(c)) System.out.println("b.equals(c) is true"); if (Arrays.equals(a, b)) System.out.println("a and b have the same elements"); if (Arrays.equals(a, c)) System.out.println("a and c have the same elements"); if (Arrays.equals(b, c)) System.out.println("b and c have the same elements");
A copy of the reference is passed so the formal parameter is an alias for the actual parameter.
// This function will swap the values of // elements 0 and 1 in the array duo // public static void swapElements(int[] duo) { int temp; temp = duo[0]; duo[0] = duo[1]; duo[1] = temp; }
public class GradeBook { private double[] grades; private String course; public GradeBook(String c, int n) { this.course = c; this.grades = new double[n]; } // ... public double getGrade(int index) { if (index < this.grades.length) return this.grades[index]; else return -1; } }
GradeBook gb; gb = new GradeBook("CS100", 3); // ... System.out.printf("Grade %d: %f5.1\n", i, gb.getGrade(i));
public class GradeBook { private double[] grades; private String course; public GradeBook(String c, double[] g) { this.course = c; this.grades = g; } // ... public double getGrade(int index) { if (index < this.grades.length) return this.grades[index]; else return -1; } }
double[] exams = {100.0, 95.0, 100.0}; GradeBook gb; gb = new GradeBook("CS100", exams); // ... System.out.printf("Grade %d: %f5.1\n", 1, gb.getGrade(1)); exams[1] = 10.0; System.out.printf("Grade %d: %f5.1\n", 1, gb.getGrade(1));
public class GradeBook { private double[] grades; private String course; public GradeBook(String c, double[] g) { int n; this.course = c; n = g.length; this.grades = new double[n]; for (int i = 0; i < n; i++) { this.grades[i] = g[i]; } } }
double[] exams = {100.0, 95.0, 100.0}; GradeBook gb; gb = new GradeBook("CS100", exams); // ... System.out.printf("Grade %d: %f5.1\n", 1, gb.getGrade(1)); exams[1] = 10.0; System.out.printf("Grade %d: %f5.1\n", 1, gb.getGrade(1));
clone()
Method
clone()
creates a shallow copy so each element in
copy
will contain the same reference as the
corresponding element in original
Movie[] copy, original; original = new Movie[4]; original[0] = new Movie("Shrek", 2001); original[1] = new Movie("Toy Story", 1995); original[2] = new Movie("Monsters, Inc.", 2001); original[3] = new Movie("Who Framed Roger Rabbit", 1988) ; copy = original.clone();
java.util.Arrays
Revisited
The methods in the java.util.Arrays
utility class can change
the elements in the arrays that they are passed because
arrays are reference types.
import java.util.Arrays; int target; int[] a; a = new int[100]; Arrays.fill(a, 0); // Fill a with zeroes Arrays.fill(a, 1, 10, 99) // Fill a[10] thru a[99] with ones ... Arrays.sort(a); // Sort a in ascending order
max()
method)...
after the type of the last
formal parameter/** * Calculate the maximum of a set of int values. * * @param data The int values of interest * @return The maximum */ public static int max(int... data) { int result = data[0]; for (int i=1; i<data.length; i++) { if (data[i] > result) result = data[i]; } return result; }
int high = Numeric.max(90, 85, 50, 100, 20);