The labs on this site need JavaScript to run. The same content is written out below.
Learn › Java › Basic syntax
Arrays
Does assigning an array variable copy the array?
An array is a fixed number of elements of the same type placed side by side. The number of an element (its index) starts at 0, the length is set when the array is created and does not change, and every element is filled with a default value as soon as the array is created. An array is an object too, so a variable holds a reference to the array. That is why b = a does not copy the array, and why a two-dimensional array is "an array whose elements hold arrays".
Checked against real execution · Checked by running 72 combinations on JDK 21
Concepts in this lab
- Array
- This is an object that holds a fixed number of values of the same type side by side. You create one as in int[] a = new int[3], and the number of an element (its index) starts at 0 and goes up to length - 1. The length is set when the array is created, does not change, and is read with a.length. As soon as an array is created, every element is filled with a default value (0 for numbers, false for boolean, null for reference types), and using an index outside the range throws an ArrayIndexOutOfBoundsException at run time. An array is an object too, so an array variable holds a reference to the array, and when it is assigned to another variable, the two variables refer to the same array.
- Shallow copy and deep copy
- A shallow copy creates anew only the outermost level of an object or an array and copies the references inside it as they are. So the copy and the original refer to the same inner objects, and when an inner object is changed through one, the change is visible through the other too. clone() of an array and Arrays.copyOf make shallow copies, and when they are used on a two-dimensional array, only the outer array is newly created and the row arrays are shared. A deep copy creates anew everything down to the inner objects and so keeps the copy completely separate from the original, and for a two-dimensional array this means that each row must be cloned. If what the elements hold is primitive values or immutable objects, a shallow copy alone is enough for the two not to affect each other.
- Primitive types and reference types
- These are the two kinds into which the types of Java are divided. There are eight primitive types, byte, short, int, long, float, double, char, and boolean, and a variable of one of them holds the value itself. Reference types are all the other types, such as classes, interfaces, and arrays, and a variable of one of them holds a reference to an object, not the object itself. So assigning a variable of a primitive type copies the value, and the two variables do not affect each other, but assigning a variable of a reference type copies the reference, and the two variables come to refer to the same object. A variable of a reference type can hold null, which means that it refers to no object, and a variable of a primitive type cannot hold null.
- ArrayList
- This is a list that keeps an array inside and moves the elements to a larger array when the array is full. Access to an element by index is fast at O(1), and adding at the end is also O(1) amortized. Inserting or removing in the middle takes O(n), because the elements after that position must each be shifted by one position.
Try these
- Default settings — After the assignment b = a, a value is stored in an element through b. Printing a shows that value too.
- Copying with clone — There are now two arrays, so a stays the same.
- Storing at an index equal to the length — Three elements have only the indexes 0, 1, and 2. Storing at index 3 throws an exception.
- Initial state of a String array — An element in which no value has been stored holds null.
- A two-dimensional array is an array of arrays — One outer array and two row arrays, three in all, are created.
- Cloning a two-dimensional array — The value in a changes even though a copy was made. That is because the row arrays are shared.
Running with the default settings
- int[] a = new int[3]: An array of 3 int elements placed side by side is created on the heap. The elements are numbered 0, 1, 2 from the front (the index). No value has been stored yet, but every element is filled with the default value (the default value of int is 0). The variable a holds a reference to this array.
- int[] b = a: The reference that a holds is copied to b. No new array is created. a and b refer to the same single array.
- System.out.println(a == b): This compares whether the two variables refer to the same array. The output is true.
- b[2] = 7: The value is stored in the array that b refers to, at index 2. With a length of 3, the indexes go from 0 through 2, so index 2 is the last element.
- System.out.println(Arrays.toString(a)): The contents of the array that a refers to are printed. The output is [0, 0, 7]. The value stored through b is visible through a too. That is because a and b refer to the same array.
- System.out.println(Arrays.toString(b)): The contents of the array that b refers to are printed. The output is [0, 0, 7].
Result of this run
- Assigning an array variable does not copy the array. It gives you one more variable that refers to the same array. So a value stored through one is visible through the other too. The same is true when you pass an array to a method.
- When an array is created, every element is filled with a default value. It is 0 for numeric types, false for boolean, and null for reference types.
Code
import java.util.Arrays;
int[] a = new int[3]; // 3 elements, filled with the default value
int[] b = a; // only the reference is copied
System.out.println(a == b);
b[2] = 7; // stores at index 2
System.out.println(Arrays.toString(a));
System.out.println(Arrays.toString(b));
Assumptions of this model
The results of the 72 combinations (a == b, the exception and its message, and the two outputs) were checked against the result of running code with the same structure on JDK 21 on this PC. Of the points made in the summary, the following were also confirmed by running them: getting a longer array with Arrays.copyOf, rows not being shared when each row is cloned, a change made inside a method to an array passed to it being visible outside, an exception being thrown when a loop runs with i <= a.length, a NullPointerException being thrown when a method is called on a null element, and the values of a.length and a[0].length. The wording of the exception message can differ from one JDK version to another, and the one given here is that of JDK 21. Whether the elements of an array are actually placed side by side in memory was not confirmed by execution. It is an explanation that follows the way a JVM is generally implemented. In the diagram, the String value "A" is written directly in the element, but the element actually holds a reference to a String object. Creating an array by writing out its values, as in { 1, 2, 3 }, two-dimensional arrays whose rows have different lengths, and the enhanced for statement are not covered.
Previous lab: Conditionals and loops · Next lab: Classes, objects, and constructors