Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

Java  Module 4 – Arrays and strings in depth

Arrays: creation, indexing and iteration

Create Java arrays with new and with initialisers, read and write them by index, loop with for and for-each, and copy them without aliasing bugs.

  • Beginner
  • 25 minutes
  • Examples run with Java temurin-25.0.4+101.0.LTS
  • By MySmartCoPilot
Free lesson, Pro answers: 25 minutes
Free: the whole lesson. With a pass: the model answers to its 2 interview questions.

What you will learn

  • Create arrays with new and with initialisers, and predict the default value of every new element
  • Loop over an array with for and for-each without stepping past its last index
  • Display an array's elements with Arrays.toString instead of its class name and hash code
  • Copy an array with clone, Arrays.copyOf or System.arraycopy instead of sharing it by assignment
  • Predict what a method call or a store through an Object[] does to an array

Before you start

What you’ll learn · Before you start

What you will learn

  • Create arrays with new and with initialisers, and predict the default value of every new element
  • Loop over an array with for and for-each without stepping past its last index
  • Display an array's elements with Arrays.toString instead of its class name and hash code
  • Copy an array with clone, Arrays.copyOf or System.arraycopy instead of sharing it by assignment
  • Predict what a method call or a store through an Object[] does to an array

Before you start

On this page

Six students’ marks in six separate variables need six names, and every total, average or search has to mention all six. An array keeps a fixed number of values of one type together in one object, numbered from 0: int[] marks = new int[5]; creates five int elements that all start at 0, and int[] marks = {71, 64, 88, 92, 57}; creates five with those values. The JVM checks every index you use, and an array variable holds a reference to the array, so int[] b = a; gives one array a second name instead of copying it.

You will create arrays and loop over them without stepping past the end, step through what an assignment, a copy and a method call do to one array, and meet the two errors arrays are known for. Every program is a compact source file: A .java file whose fields and methods are written with no class declaration around them, such as a file that holds only a main method. JEP 512 made it a permanent part of Java in JDK 25. More in “Your first program: a compact source file”, run with java Name.java on JDK 25.

new int[5] fixes the length and fills in default values

Defaults.java creates arrays in three ways, prints what each new array holds before anything is stored in it, and then asks for a negative length:

New arrays, an initialiser and a negative length Java · Defaults.java
// Three ways to create an array, what a new array holds before anything is stored in it,
// and what happens when the length is negative.
void main() {
    int[] marks = new int[5];               // five ints
    double[] prices = new double[3];
    boolean[] present = new boolean[4];
    char[] initials = new char[2];
    String[] names = new String[3];         // three references, no String objects yet

    IO.println("marks    " + Arrays.toString(marks) + ", length " + marks.length);
    IO.println("prices   " + Arrays.toString(prices));
    IO.println("present  " + Arrays.toString(present));
    IO.println("initials " + (int) initials[0] + " and " + (int) initials[1]
            + " (character codes)");
    IO.println("names    " + Arrays.toString(names));

    int[] days = {31, 28, 31, 30};          // an initialiser: the compiler counts the values
    int[] none = {};                        // an empty array, which is not the same as null
    String[] cities;
    cities = new String[] {"Pune", "Kochi"};  // outside a declaration, name the type
    IO.println("days " + days.length + ", none " + none.length + ", cities " + cities.length);

    int n = -1;
    try {
        int[] wrong = new int[n];
    } catch (NegativeArraySizeException e) {
        IO.println("new int[-1]: " + e);
    }
}

Output

marks    [0, 0, 0, 0, 0], length 5
prices   [0.0, 0.0, 0.0]
present  [false, false, false, false]
initials 0 and 0 (character codes)
names    [null, null, null]
days 4, none 0, cities 2
new int[-1]: java.lang.NegativeArraySizeException: -1

Recorded with OpenJDK 25.0.4.1 LTS (Eclipse Temurin) on macOS 26 arm64. To run it yourself: java Defaults.java

Version note

Compact source files and IO.println are final in JDK 25 (JEP 512), and such a file imports the whole java.base module, which is why Arrays needs no import line. On JDK 21 or older, put the same code in a class with public static void main(String[] args), write System.out.println instead of IO.println, add import java.util.Arrays;, and declare the other methods static so that main can call them.

  • new int[5] fixes the length and fills in default values. The Java Language Specification gives every array element a default value: The value every element of a new array starts with, before anything is stored in it: 0 for the integer types, 0.0 for float and double, false for boolean, the character with code 0 for char, and null for every reference type. when the array is created, the one the table below lists for its type. A new String[3] therefore holds three nulls, not three empty strings: no String objects exist until you store some.
  • An initialiser lists the values, and the compiler counts them: days has 4 elements. The short form {31, 28, 31, 30} works only in a declaration. Anywhere else, for example when you assign the variable later or pass an array straight to a method, write the type as well: new String[] {"Pune", "Kochi"}.
  • length is a field, not a method, so it has no parentheses: marks.length, but name.length() for a String. It is final. Once an array exists its length never changes, so to make room for more elements you create a longer array and copy the old ones into it, as Arrays.copyOf does further down, or use an ArrayList, which does that for you and has a lesson in the collections module.
  • An empty array is not null. none has length 0, and a loop over it simply runs zero times. A variable that holds null refers to no array at all, and reading its length throws NullPointerException.
  • A negative length is a run-time error. The compiler cannot know what n will hold, so new int[n] with n = -1 compiles and then throws NegativeArraySizeException. A length of 0 is fine.

What a new element holds, by its type, with the lines of the run that show it:

Element type A new element holds
int, and byte, short, long 0: marks printed [0, 0, 0, 0, 0]
double and float 0.0: prices printed [0.0, 0.0, 0.0]
boolean false: present printed four of them
char the character with code 0, printed as the number 0
String and every other reference type null: names printed [null, null, null]

Write the brackets after the type, int[] marks. Java also accepts the C style, int marks[], but the specification recommends against mixing the two styles in one declaration, and int[] marks keeps the whole type in one place.

Checkpoint

Check: Array length and default values

  1. Question 1 of 2 String[] names = new String[3]; What happens when the next line is IO.println(names[0].length());?

    Choose one answer.

    A hint

    What does each element of a new String[] hold before anything is stored in it?

    Show the answer: Question 1 of 2

    Answer: It throws NullPointerException

    A new array of references starts with null in every element, as Defaults.java printed for names: [null, null, null]. No String object exists until you store one, so names[0].length() calls a method on null and throws NullPointerException.

  2. Question 2 of 2 int[] days; was declared earlier. Which line then gives days the values 31, 28 and 31?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: days = new int[] {31, 28, 31};

    An initialiser on its own, {31, 28, 31}, works only in a declaration. Anywhere else, write the type with it, new int[] {31, 28, 31}, as Defaults.java did with new String[] {"Pune", "Kochi"}.

The JVM checks every index you use

marks[0] is the first element and marks[marks.length - 1] the last; marks[2] = 90; replaces the third. The index can be any expression of type int (a long index does not compile), and the JVM checks it every time the access runs. The usual way to trip that check is a loop condition written with <=:

One index too many Java · OffByOne.java
// The classic off-by-one mistake: i <= marks.length visits one index too many.
void main() {
    int[] marks = {71, 64, 88, 92, 57};
    int total = 0;
    for (int i = 0; i <= marks.length; i++) {    // the last valid index is marks.length - 1
        total += marks[i];
        IO.println("i = " + i + ": total " + total);
    }
    IO.println("total: " + total);               // never reached
}

Output (exit status 1)

i = 0: total 71
i = 1: total 135
i = 2: total 223
i = 3: total 315
i = 4: total 372

Printed as an error (standard error)

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 5
	at OffByOne.main(OffByOne.java:6)

Recorded with OpenJDK 25.0.4.1 LTS (Eclipse Temurin) on macOS 26 arm64. To run it yourself: java OffByOne.java

The loop printed five running totals and then stopped. Step through it to see why a sixth pass started at all, and where the check caught it:

Interactive · stage by stage Six passes over five marks, and the check that stops the sixth Step through the loop of OffByOne.java one pass at a time and watch the test let i reach 5.
Six passes over five marks, and the check that stops the sixth, step 6 of 6. Showing i <= marks.length ? (5 <= 5: true), total += marks[i]; (index 5: outside 0 to 4), after the loop (never runs). In focus: after the loop.i++false: leavei <= marks.length ?5 <= 5: truetotal += marks[i];index 5: outside 0 to 4after the loopnever runs

The drawing shows the whole scene; its 6 steps are listed below.

Every step as text
  1. Pass 1. i is 0, and 0 <= 5 is true. Index 0 is inside 0 to 4, so marks[0], 71, is added, and the run prints i = 0: total 71.
  2. Passes 2 to 4. 64, 88 and 92 follow at the indexes 1, 2 and 3, and the printed total grows to 135, 223 and 315.
  3. Pass 5, the last index. i is 4, the last valid index of a five-element array. marks[4] is 57, and the run prints i = 4: total 372.
  4. A sixth pass. i++ makes i 5, and 5 <= 5 is still true, so the loop starts a sixth pass over an array that has five elements.
  5. The index check. marks[5] asks for index 5 of an array of length 5. The JVM checks the index before it reads anything, finds it outside 0 to 4 and throws ArrayIndexOutOfBoundsException at line 6.
  6. Never printed. The exception ends main, so the line after the loop never runs. With i < marks.length the sixth test would be false, and the loop would leave after the fifth pass.

The message says what happened, Index 5 out of bounds for length 5, and the line under it, the top of the stack trace: What an uncaught exception prints: its class and message, then the calls that were open when it was thrown, the most recent first, each with its file and line, and any Caused by sections. More in “IDEs, compiler errors and your first debug”, says where: line 6 of OffByOne.java. A five-element array has the indexes 0 to 4, and i <= marks.length lets i reach 5. The program stopped at that access, so the line after the loop never ran, and nothing was read from outside the array. An index below 0 fails in the same way.

Testing i <= a.length

for (int i = 0; i <= marks.length; i++) runs one pass too many, the classic off-by-one error: A loop that runs one pass too many or too few, usually from < written where <= was meant, or from a counter that starts at the wrong value. Checking the first and the last pass by hand catches it. More in “Loops: while, do-while, for and for-each”, and that pass throws. Write i < marks.length: the last index is always length - 1.

Checkpoint

Check: Indexes and the bounds check

  1. Question 1 of 2 int[] seats = new int[40]; What is the largest index that seats accepts?

    Type a number.

    A hint

    The first index is 0.

    Show the answer: Question 1 of 2

    Answer: 39

    Indexes run from 0 to length - 1, so a 40-element array accepts 0 to 39. seats[40] would throw ArrayIndexOutOfBoundsException: Index 40 out of bounds for length 40.

  2. Question 2 of 2 Which loop header visits every element of marks exactly once?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: for (int i = 0; i < marks.length; i++)

    Start at 0 and stop before length: i < marks.length. The run of OffByOne.java showed what the <= version does, a sixth pass over five elements.

for-each gives you the values, and an indexed loop the positions too

Both loops from the lesson on loops work on arrays. The enhanced for loop: for (T x : items), also called for-each: it gives x each element of an array or an Iterable in turn, with no index, so it cannot step past the end, and x holds a copy of each element. More in “Loops: while, do-while, for and for-each”, for (int m : marks), gives you each value in turn, with no index to get wrong. The indexed loop, for (int i = 0; i < marks.length; i++), gives you the position as well. With arrays, the choice mostly comes down to whether you need that position:

Statistics over six marks Java · Marks.java
// Statistics over one test's marks (out of 100). A for-each loop where only the values matter,
// an indexed loop where the position matters too.
void main() {
    String[] names = {"Asha", "Ravi", "Meera", "Kabir", "Divya", "Arjun"};
    int[] marks = {71, 64, 88, 92, 57, 88};      // marks[i] belongs to names[i]

    int total = 0;
    for (int m : marks) {                        // every value, no index to get wrong
        total += m;
    }
    double average = (double) total / marks.length;

    int best = 0;                                // the INDEX of the highest mark so far
    for (int i = 1; i < marks.length; i++) {
        if (marks[i] > marks[best]) {
            best = i;
        }
    }

    int above = 0;
    for (int m : marks) {
        if (m > average) above++;
    }

    IO.println("students: " + marks.length + ", total: " + total);
    IO.println("average: " + String.format("%.2f", average));
    IO.println("highest: " + marks[best] + " by " + names[best] + " (index " + best + ")");
    IO.println("above the average: " + above);
}

Output

students: 6, total: 460
average: 76.67
highest: 92 by Kabir (index 3)
above the average: 3

Recorded with OpenJDK 25.0.4.1 LTS (Eclipse Temurin) on macOS 26 arm64. To run it yourself: java Marks.java

The total and the count above the average need only the values, so for-each is the clearer loop for them. Finding who scored highest needs a position: best holds the index of the best mark so far, and names[best] uses the same index in the second array. Two arrays kept in step like this are called parallel arrays: Two or more arrays kept in step by index, such as names[i] and marks[i] for one student. Sorting or changing one of them without the others breaks the link, which is why one array of records is usually safer.. They work, but the next lesson shows how sorting one of them separates names from marks, and the cure, an array of records. Two details matter in the arithmetic: (double) total / marks.length makes the division a decimal one (without the cast, 460 / 6 is 76), and starting with best = 0 assumes the array has at least one element. An empty array would make marks[best] throw, so a method that might receive one checks marks.length first.

What the loop does The loop to use
Reads every value: a total, a count, a print for-each
Needs the position: names[best] indexed
Stores into the array: marks[i] = … indexed
Visits some positions only, or goes backwards indexed
Descriptive Statistics Calculator Enter the six marks to check the total, the average and the highest mark against the program's output.

The specification defines the for-each loop over an array as an indexed loop that assigns a[i] to the loop variable at the start of every pass. So the variable is a copy of the element, and assigning to it never changes the array, as the lesson on loops showed with numbers. In an array of objects, each element is a reference, and the copy refers to the same object:

A for-each loop over an array of builders Java · ForEachObjects.java
// The variable of a for-each loop is a copy of each element. In an array of objects, each
// element is a reference, so the loop can change the objects themselves, but it cannot put
// another object into the array.
void main() {
    StringBuilder[] labels = {
        new StringBuilder("A1"), new StringBuilder("A2"), new StringBuilder("A3"),
    };
    for (StringBuilder label : labels) {
        label.append('*');                        // changes the object this element refers to
    }
    IO.println("after append: " + Arrays.toString(labels));
    for (StringBuilder label : labels) {
        label = new StringBuilder("??");          // redirects only the loop's copy
    }
    IO.println("after assign: " + Arrays.toString(labels));
}

Output

after append: [A1*, A2*, A3*]
after assign: [A1*, A2*, A3*]

Recorded with OpenJDK 25.0.4.1 LTS (Eclipse Temurin) on macOS 26 arm64. To run it yourself: java ForEachObjects.java

Step through both loops, one reference at a time:

Interactive · step by step What a for-each loop can change in an array of objects Step through both loops of ForEachObjects.java. Boxes on the left hold references; boxes on the right are the objects.
What a for-each loop can change in an array of objects, step 6 of 6. Showing labels[0], labels[1], labels[2], label, a StringBuilder (holds A1*), a StringBuilder (holds A2*), a StringBuilder (holds A3*), a new StringBuilder. In focus: labels[0], labels[1], labels[2].labels[0]labels[1]labels[2]labelthe loop variablea StringBuilderholds A1*a StringBuilderholds A2*a StringBuilderholds A3*a new StringBuilderholds ??

The drawing shows the whole scene; its 6 steps are listed below.

Every step as text
  1. Three elements, three objects. labels is an array of three references, and each element refers to its own StringBuilder, holding A1, A2 and A3.
  2. The variable is a copy. The first pass of the first loop copies labels[0] into label. Both now hold the same reference, so both lead to the builder holding A1.
  3. append changes the object. label.append('') changes the object that label and labels[0] both refer to, so the array's first element now shows A1.
  4. Passes 2 and 3. The next passes copy labels[1] and labels[2] into label in turn and append to their objects. The first println prints after append: [A1*, A2*, A3*].
  5. Assigning to the copy. In the second loop, label again starts as a copy of labels[0]. label = new StringBuilder("??") makes the copy refer to a new object, and labels[0] still refers to A1*.
  6. The array is unchanged. Every pass redirects only its own copy, so the second println prints after assign: [A1*, A2*, A3*] again. Only labels[i] = … puts a different object into an element.

label.append('*') changed the object that the element and the copy both refer to, which the array then shows. Assigning label = new StringBuilder("??") only redirected the copy, and the array kept its three builders. To put a different object into an element, you need its index: labels[i] = ….

Checkpoint

Check: for-each and indexed loops

  1. Question 1 of 2 What does this print?

    Read the code, then choose one answer.

    int[] a = {1, 2, 3};
    for (int x : a) {
        x = x * 10;
    }
    IO.println(Arrays.toString(a));
    Show the answer: Question 1 of 2

    Answer: [1, 2, 3]

    The specification defines this loop as an indexed loop that copies a[i] into x at the start of every pass, so x = x * 10 changes the copy only. To change the elements, loop over the indexes and store into a[i].

  2. Question 2 of 2 Which job needs an indexed loop rather than a for-each loop?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: Adding 2 to every element of marks

    for-each reads values; an indexed loop also gives the position, which you need to store into the array, to use the same index in a parallel array, or to visit only some positions.

println shows an array’s class and hash code, and Arrays.toString its elements

Passing an array to IO.println or System.out.println does not print its elements:

println against Arrays.toString Java · Printing.java
// What println shows for an array, and what Arrays.toString shows.
void main() {
    int[] marks = {71, 64, 88};
    String[] cities = {"Pune", "Kochi"};
    IO.println(marks);                           // its type and a hash code, not the elements
    IO.println(cities);
    IO.println(Arrays.toString(marks));          // the elements
    IO.println(Arrays.toString(cities));
    int[] missing = null;
    IO.println(Arrays.toString(missing));        // "null", without an exception
}

Output

[I@120d6fe6
[Ljava.lang.String;@4ba2ca36
[71, 64, 88]
[Pune, Kochi]
null

This output changes from run to run: the hexadecimal number after each @ is a hash code, which may differ from one run to the next

Recorded with OpenJDK 25.0.4.1 LTS (Eclipse Temurin) on macOS 26 arm64. To run it yourself: java Printing.java

An array inherits toString from Object, which returns the name of the object’s class, an @ and the object’s hash code in hexadecimal. The five lines of the run, one by one:

The run printed What it is
[I@ and a hash code [I is how the JVM names the class of int[]
[Ljava.lang.String;@ and a hash code the name of the class of String[]
[71, 64, 88] Arrays.toString(marks): the elements
[Pune, Kochi] Arrays.toString(cities)
null Arrays.toString(missing) for a null array

The hash code identifies the object, not its contents, and the Object documentation warns that this text may change from one run to the next. Arrays.toString is what you want: the elements in square brackets, separated by commas. It also accepts null and returns the text null instead of throwing.

Checkpoint

Check: Printing an array

  1. One question What does IO.println(new int[] {4, 5}); print?

    Choose one answer.

    Show the answer: One question

    Answer: [I@ followed by a hexadecimal hash code

    An int[] has the class name [I, so println shows [I@ and a hash code, as the first line of Printing.java did. Arrays.toString(new int[] {4, 5}) gives [4, 5].

An array variable holds a reference, and an assignment shares it

An array is an object. The JVM allocates it on the The memory where the JVM keeps the objects a program creates, shared by the whole program. A variable never holds an object itself, only a reference to one there., and an array variable holds a reference to it, just as a String variable holds a reference to a string. An assignment between two array variables duplicates that reference and nothing else, which leaves you with two names for one set of elements:

Variables marks and backup both point to one int array of five elements; cloned points to a second array holding a copy.marksbackupclonedan int[5] objectits clone71648892757164889275

After int[] backup = marks; and int[] cloned = marks.clone();

Text description of the diagram

The diagram shows three array variables and the two array objects they refer to.

  1. marks refers to an array object of length 5 holding 71, 64, 88, 92 and 75.
  2. backup was declared as int[] backup = marks. That copied only the reference, so backup refers to the same array object. A change made through marks, such as marks[4] = 75, is seen through backup too, and marks == backup is true.
  3. cloned was declared as int[] cloned = marks.clone(). That created a second array object with its own copy of the five elements, so a later change to marks leaves cloned as it was, and cloned == marks is false.
A backup that changes with the original, and three real copies Java · Aliasing.java
// A "backup" that is not a backup: assigning an array variable copies the reference,
// not the elements.
void main() {
    int[] marks = {71, 64, 88, 92, 57};
    int[] backup = marks;                        // one array with two names

    marks[4] = 75;                               // a re-evaluated paper
    IO.println("marks  " + Arrays.toString(marks));
    IO.println("backup " + Arrays.toString(backup) + "  <- changed as well");
    IO.println("marks == backup: " + (marks == backup));

    // Three ways to copy the elements into a new array.
    int[] cloned = marks.clone();
    int[] copied = Arrays.copyOf(marks, marks.length);
    int[] longer = Arrays.copyOf(marks, 7);      // extra elements are 0
    int[] target = new int[5];
    System.arraycopy(marks, 0, target, 0, marks.length);

    marks[0] = 0;                                // change the original again
    IO.println("marks  " + Arrays.toString(marks));
    IO.println("cloned " + Arrays.toString(cloned) + ", cloned == marks: " + (cloned == marks));
    IO.println("copied " + Arrays.toString(copied));
    IO.println("longer " + Arrays.toString(longer));
    IO.println("target " + Arrays.toString(target));
}

Output

marks  [71, 64, 88, 92, 75]
backup [71, 64, 88, 92, 75]  <- changed as well
marks == backup: true
marks  [0, 64, 88, 92, 75]
cloned [71, 64, 88, 92, 75], cloned == marks: false
copied [71, 64, 88, 92, 75]
longer [71, 64, 88, 92, 75, 0, 0]
target [71, 64, 88, 92, 75]

Recorded with OpenJDK 25.0.4.1 LTS (Eclipse Temurin) on macOS 26 arm64. To run it yourself: java Aliasing.java

backup was meant to keep the old marks, yet it shows 75 straight away: int[] backup = marks; made no copy, and marks == backup is true because == on arrays compares references. It asks whether two variables lead to the same object, never whether two arrays hold the same values. Two names for one object are alias: A second name for the same object: after int[] b = a; both variables refer to one array, so a change made through either is seen through the other, and a == b is true.. Step through the program and watch the arrows:

Interactive · step by step One array with two names, and a clone with its own elements Step through Aliasing.java. Boxes on the left are array variables, boxes on the right are array objects, and an arrow is a reference.
One array with two names, and a clone with its own elements, step 5 of 5. Showing marks, backup, cloned, an int[5] object (0 64 88 92 75), its clone. In focus: an int[5] object, its clone.marksan int[] variablebackupa second variablecloneda third variablean int[5] object0 64 88 92 75its clone71 64 88 92 75

The drawing shows the whole scene; its 5 steps are listed below.

Every step as text
  1. One array. int[] marks = {71, 64, 88, 92, 57}; creates one array object, and marks holds a reference to it.
  2. A second name. int[] backup = marks; copies the reference and nothing else. backup is a second name for the same object, and no element was copied.
  3. A change seen through both. marks[4] = 75 writes into the only array there is, so marks and backup both print [71, 64, 88, 92, 75], and marks == backup is true.
  4. A real copy. marks.clone() creates a second array with its own copy of the five elements. Arrays.copyOf and System.arraycopy into a new int[5] make copies like it.
  5. Only the original changes. marks[0] = 0 changes the original, which backup still shares, while the clone keeps 71 at index 0, and cloned == marks is false.

A backup made with =

int[] backup = marks; makes a second name, not a backup: the run’s backup changed as soon as marks[4] did. Write int[] backup = marks.clone();, or Arrays.copyOf(marks, marks.length), before you change anything.

Each of the three real copies is a new array, so each keeps its values when marks changes again:

  • marks.clone() returns a new array of the same type and length with the same elements. Every array has this public clone method, and for an int[] it returns an int[], so no cast is needed.
  • Arrays.copyOf(marks, n) returns a new array of length n. A shorter length cuts elements off; a longer one pads with the default value, here 0. It is the usual way to grow an array.
  • System.arraycopy(src, srcPos, dest, destPos, length) copies into an array you already have, starting at any position on either side. When the two ranges overlap inside one array, it behaves as if it had copied through a temporary array, so the result is still right.

These copies are complete only for arrays of primitive type: One of the eight value types built into Java: byte, short, int, long, float, double, char and boolean. A variable of a primitive type holds the value itself and has no methods. More in “Variables and the eight primitive types” values. A copy of a String[], or of any array of objects, holds the same references, so both arrays point to the same objects: a shallow copy: A copy that copies the references an array or object holds but not the objects they refer to, so the copy and the original share those objects. clone() on an int[][] copies only the outer array of row references. More in “2D and jagged arrays for grids and matrices”, and the lesson on two-dimensional arrays shows where it bites. To compare two arrays by their contents, use Arrays.equals(a, b), which the next lesson covers with the rest of the Arrays class.

Key idea

b = a copies a reference, so both names reach one array; clone(), Arrays.copyOf and System.arraycopy into a new array copy the elements.

Checkpoint

Check: References, aliases and copies

  1. Question 1 of 2 What does this print?

    Read the code, then choose one answer.

    int[] a = {1, 2, 3};
    int[] b = a;
    b[0] = 9;
    IO.println(a[0]);
    Show the answer: Question 1 of 2

    Answer: 9

    There is one array with two names, as backup and marks were in Aliasing.java. Writing b[0] writes the only array there is, and a[0] reads it back as 9.

  2. Question 2 of 2 int[] longer = Arrays.copyOf(new int[] {71, 64, 88}, 5); What is longer[4]?

    Type a number.

    A hint

    What does copyOf put into the places the original does not have?

    Show the answer: Question 2 of 2

    Answer: 0

    A longer copy is padded with the default value, so longer is [71, 64, 88, 0, 0], just as the run's longer was padded with two zeros. longer[4] is 0.

A method gets the reference by value, so it can change your elements

A method parameter of an array type receives a copy of the caller’s reference, never a copy of the array. Java passes every argument this way, pass-by-value: Passing a copy of each argument's value to the method's parameter, which is how Java passes every argument. For an object the value copied is a reference, so the method can change the object but never the caller's variable. More in “Methods, parameters, return and overloading”, and the value of an array variable is a reference:

What a method can and cannot change Java · Methods.java
// A method receives a copy of the reference. It can change the caller's elements,
// but pointing its own parameter at another array changes nothing for the caller.
void addGrace(int[] marks) {
    for (int i = 0; i < marks.length; i++) {
        marks[i] += 2;                           // writes into the caller's array
    }
}

void replace(int[] marks) {
    marks = new int[] {100, 100, 100};           // only the parameter points elsewhere now
}

int[] withGrace(int[] marks) {
    int[] result = marks.clone();                // leave the caller's array as it is
    for (int i = 0; i < result.length; i++) {
        result[i] += 2;
    }
    return result;
}

void main() {
    int[] marks = {71, 64, 88};
    addGrace(marks);
    IO.println("after addGrace: " + Arrays.toString(marks));
    replace(marks);
    IO.println("after replace:  " + Arrays.toString(marks));
    int[] graced = withGrace(marks);
    IO.println("withGrace returned " + Arrays.toString(graced)
            + ", marks is still " + Arrays.toString(marks));
}

Output

after addGrace: [73, 66, 90]
after replace:  [73, 66, 90]
withGrace returned [75, 68, 92], marks is still [73, 66, 90]

Recorded with OpenJDK 25.0.4.1 LTS (Eclipse Temurin) on macOS 26 arm64. To run it yourself: java Methods.java

Step through the three calls and watch which arrows each method can move:

Interactive · step by step What addGrace, replace and withGrace can do to main's array Step through the three calls. Boxes on the left are variables of main and of each method; an arrow is a reference.
What addGrace, replace and withGrace can do to main's array, step 6 of 6. Showing main: marks, withGrace: result, main's int[3] (73 66 90), the clone. In focus: withGrace: result, the clone.main: markswithGrace: resultrefers to a clonemain's int[3]73 66 90the clone75 68 92 after +2

The drawing shows the whole scene; its 6 steps are listed below.

Every step as text
  1. main's array. In main, marks refers to an int[3] holding 71, 64 and 88.
  2. addGrace gets a copy. addGrace(marks) passes the value of main's variable, which is a reference. The parameter marks is a copy of it, so it refers to the same array.
  3. It writes through the copy. marks[i] += 2 writes into that one array, which becomes 73, 66 and 90, so main prints after addGrace: [73, 66, 90].
  4. replace gets a copy too. addGrace has returned and its parameter is gone. replace(marks) starts the same way: its parameter is another copy of main's reference.
  5. Only the copy moves. marks = new int[] {100, 100, 100}; points the parameter at a new array. main's variable still refers to 73, 66 and 90, which main prints again.
  6. withGrace copies first. withGrace clones the array before it changes anything, adds 2 only to the clone and returns [75, 68, 92], while main's marks are still [73, 66, 90].

addGrace changed the caller’s marks, because it wrote through the shared reference. replace changed nothing for the caller: assigning a new array to marks inside the method only moved that method’s own copy of the reference. withGrace is the safe pattern for a method that must leave its argument alone: copy first, change the copy, return it. A method that changes an array it was given, without saying so, is one of the most common sources of bugs with arrays, so when a method does change its argument, make that clear in its name and its documentation.

Checkpoint

Check: Arrays passed to methods

  1. One question What does main print?

    Read the code, then choose one answer.

    void reset(int[] a) {
        a = new int[a.length];
    }
    
    void zeroFirst(int[] a) {
        a[0] = 0;
    }
    
    void main() {
        int[] m = {5, 6};
        reset(m);
        zeroFirst(m);
        IO.println(Arrays.toString(m));
    }
    Show the answer: One question

    Answer: [0, 6]

    Each parameter starts as a copy of m's reference. reset redirects its copy and changes nothing the caller sees; zeroFirst writes into the shared array. m prints [0, 6].

A String[] is also an Object[], so a wrong store fails while the program runs

Arrays are array covariance: The rule that an array of a subtype is also an array of its supertype, so a String[] may be assigned to an Object[]. The JVM then checks every store into an array of references while the program runs and throws ArrayStoreException for a value of the wrong type.: because a String can be assigned to an Object, a String[] can be assigned to an Object[]. That suits methods that accept any array of objects, but it lets the compiler accept a store that cannot work:

A store the JVM refuses Java · StoreCheck.java
// Arrays are covariant: a String[] may be used wherever an Object[] is expected,
// so the JVM checks every store into an array of references while the program runs.
void main() {
    String[] cities = {"Pune", "Kochi"};
    Object[] things = cities;                    // compiles: a String[] is an Object[]
    things[0] = "Jaipur";                        // a String: allowed
    IO.println(Arrays.toString(cities));
    try {
        things[1] = 42;                          // compiles, but the array holds Strings
    } catch (ArrayStoreException e) {
        IO.println("caught " + e);
    }
    IO.println(Arrays.toString(cities));
}

Output

[Jaipur, Kochi]
caught java.lang.ArrayStoreException: java.lang.Integer
[Jaipur, Kochi]

Recorded with OpenJDK 25.0.4.1 LTS (Eclipse Temurin) on macOS 26 arm64. To run it yourself: java StoreCheck.java

Step through the two stores, first as the compiler sees them, then as the JVM does:

Interactive · step by step Two stores through an Object[] name, and the check the JVM makes Step through StoreCheck.java. The left column is what the compiler sees; the right column is the object that exists while it runs.
Two stores through an Object[] name, and the check the JVM makes, step 6 of 6. Showing cities: String[], things: Object[], the value 42, a String[2] object (Jaipur, Kochi), the store check. In focus: a String[2] object.refusedcities: String[]things: Object[]the value 42boxed to an Integera String[2] objectJaipur, Kochithe store checkis the value a String?

The drawing shows the whole scene; its 6 steps are listed below.

Every step as text
  1. A String[]. cities refers to an array object created as a String[], holding Pune and Kochi.
  2. The same object as Object[]. Object[] things = cities; compiles, because a String[] is also an Object[]. things is a second reference to the same object, which stays a String[] while the program runs.
  3. A String is stored. things[0] = "Jaipur" stores a String. The JVM checks the store, the value fits, and the next line prints [Jaipur, Kochi].
  4. 42 compiles too. things[1] = 42 also compiles: to the compiler, things is an Object[], and 42 becomes an Integer, which is an Object.
  5. The check refuses it. While the program runs, the JVM compares the value with the array's real element type. An Integer is not a String, so it throws ArrayStoreException: java.lang.Integer, and nothing is stored.
  6. The array kept its contents. The catch block prints the exception, and the last line prints [Jaipur, Kochi] again: the refused store never happened.

To the compiler, things is an Object[] and 42 is an Object, so things[1] = 42 compiles. The array object, though, was created as a String[] and keeps that type while the program runs, and the JVM checks every store into an array of references. The value is an Integer, not a String, so the store throws ArrayStoreException and the array keeps its old contents. Generic collections close this gap at compile time instead: a List<String> is not a List<Object>, so the same mistake with lists does not compile, which is one reason later modules prefer collections in the parameters of methods.

Checkpoint

Check: Covariant arrays and the store check

  1. One question Object[] boxes = new Integer[2]; is followed by boxes[0] = "7";. What happens?

    Choose one answer.

    Show the answer: One question

    Answer: It compiles, and the store throws ArrayStoreException

    This is StoreCheck.java the other way round. On JDK 25 the exception reads ArrayStoreException: java.lang.String, naming the class of the value it refused.

Practise: running totals and rotation

Complete the two methods at the top of RunningTotals.java; the rest of the file is a set of checks that call them. Both methods throw until you write them, so the first run lists eight failures and exits with status 1:

The starting point: every check fails Java · RunningTotals.java
// Your turn. Write runningTotal and rotate, then run this file until every check passes:
//     java RunningTotals.java
//
// runningTotal(a) returns a new array whose element i is a[0] + a[1] + ... + a[i]:
//     {3, 1, 4} gives {3, 4, 8}.
// rotate(a, k) returns a new array in which every element moves k places to the right,
// and the ones that fall off the end come back at the front:
//     rotate({1, 2, 3, 4, 5}, 2) gives {4, 5, 1, 2, 3}.
// A negative k moves the elements to the left.
// Neither method may change a, and each one creates exactly one new array.

int[] runningTotal(int[] a) {
    throw new UnsupportedOperationException("not written yet");
}

int[] rotate(int[] a, int k) {
    throw new UnsupportedOperationException("not written yet");
}

// ---- The checks. You do not need to change anything below this line. ----

int checks = 0;
int failed = 0;

void checkTotal(int[] a, int[] want) {
    checks++;
    String call = "runningTotal(" + Arrays.toString(a) + ")";
    int[] before = a.clone();
    try {
        compare(call, a, before, runningTotal(a), want);
    } catch (RuntimeException e) {
        fail(call + " threw " + e);
    }
}

void checkRotate(int[] a, int k, int[] want) {
    checks++;
    String call = "rotate(" + Arrays.toString(a) + ", " + k + ")";
    int[] before = a.clone();
    try {
        compare(call, a, before, rotate(a, k), want);
    } catch (RuntimeException e) {
        fail(call + " threw " + e);
    }
}

void compare(String call, int[] a, int[] before, int[] got, int[] want) {
    if (!Arrays.equals(got, want)) {
        fail(call + " returned " + Arrays.toString(got)
                + ", expected " + Arrays.toString(want));
    } else if (got == a) {
        fail(call + " returned its argument, not a new array");
    } else if (!Arrays.equals(a, before)) {
        fail(call + " changed its argument to " + Arrays.toString(a));
    }
}

void fail(String message) {
    failed++;
    IO.println("FAIL " + message);
}

void main() {
    checkTotal(new int[] {3, 1, 4}, new int[] {3, 4, 8});
    checkTotal(new int[] {7}, new int[] {7});
    checkTotal(new int[] {}, new int[] {});
    checkRotate(new int[] {1, 2, 3, 4, 5}, 2, new int[] {4, 5, 1, 2, 3});
    checkRotate(new int[] {1, 2, 3, 4, 5}, 0, new int[] {1, 2, 3, 4, 5});
    checkRotate(new int[] {1, 2, 3, 4, 5}, 7, new int[] {4, 5, 1, 2, 3});
    checkRotate(new int[] {1, 2, 3, 4, 5}, -1, new int[] {2, 3, 4, 5, 1});
    checkRotate(new int[] {}, 3, new int[] {});
    IO.println(failed + " of " + checks + " checks failed");
    if (failed > 0) System.exit(1);
}

Output (exit status 1)

FAIL runningTotal([3, 1, 4]) threw java.lang.UnsupportedOperationException: not written yet
FAIL runningTotal([7]) threw java.lang.UnsupportedOperationException: not written yet
FAIL runningTotal([]) threw java.lang.UnsupportedOperationException: not written yet
FAIL rotate([1, 2, 3, 4, 5], 2) threw java.lang.UnsupportedOperationException: not written yet
FAIL rotate([1, 2, 3, 4, 5], 0) threw java.lang.UnsupportedOperationException: not written yet
FAIL rotate([1, 2, 3, 4, 5], 7) threw java.lang.UnsupportedOperationException: not written yet
FAIL rotate([1, 2, 3, 4, 5], -1) threw java.lang.UnsupportedOperationException: not written yet
FAIL rotate([], 3) threw java.lang.UnsupportedOperationException: not written yet
8 of 8 checks failed

Recorded with OpenJDK 25.0.4.1 LTS (Eclipse Temurin) on macOS 26 arm64. To run it yourself: java RunningTotals.java

You are done when java RunningTotals.java prints 0 of 8 checks failed. The checks also catch a method that returns its argument instead of a new array, or that changes its argument: the two reference mistakes of this lesson. One hint for rotate: element i moves to index (i + k) % n, but Java’s % keeps the sign of the number on its left, so -1 % 5 is -1, not 4. Math.floorMod(-1, 5) gives 4. An empty array needs a case of its own, because % 0 throws ArithmeticException.

Then try the practice below on the seven ideas of the lesson, from default values to the store check. It opens on the array rule you miss most, and every option spells out the array behaviour behind it:

Practice that adapts to you

Practise this lesson

19 questions about 7 ideas of this lesson. Each answer is explained at once, and what you get right is kept in this browser.

  1. Question 1 of 19 After int[] counts = new int[3]; and String[] names = new String[3];, what do counts[0] and names[0] hold?

    Choose one answer.

    Show the answer: Question 1 of 19

    Answer: 0 and null

    Every element of a new array gets its type's default value: 0 for int and null for a reference such as String. No String objects exist until you store some, and Java never shows leftover memory.

  2. Question 2 of 19 int n = -1; What does int[] a = new int[n]; do?

    Choose one answer.

    Show the answer: Question 2 of 19

    Answer: It compiles, then throws NegativeArraySizeException when it runs

    The compiler cannot know what n will hold, so the length is checked while the program runs. Defaults.java printed new int[-1]: java.lang.NegativeArraySizeException: -1. A length of 0 is fine.

  3. Question 3 of 19 int[] marks holds five marks, and a sixth student's 81 must be added. Which code works?

    Choose one answer.

    Show the answer: Question 3 of 19

    Answer: marks = Arrays.copyOf(marks, 6); marks[5] = 81;

    An array never grows. To make room, create a longer array, copy the elements into it and point the variable at it, which is what Arrays.copyOf does in one call.

  4. Question 4 of 19 marks has 5 elements. What happens when this loop runs?

    Read the code, then choose one answer.

    int total = 0;
    for (int i = 0; i <= marks.length; i++) {
        total += marks[i];
    }
    Show the answer: Question 4 of 19

    Answer: It throws ArrayIndexOutOfBoundsException when i reaches 5

    The valid indexes are 0 to 4. The condition i <= marks.length lets i reach 5, and the JVM checks every access, so marks[5] throws with the message "Index 5 out of bounds for length 5". The condition should be i < marks.length.

  5. Question 5 of 19 A program stops with ArrayIndexOutOfBoundsException: Index 7 out of bounds for length 7. What did it do?

    Choose one answer.

    Show the answer: Question 5 of 19

    Answer: It asked for index 7 of an array whose indexes are 0 to 6

    An array of length n has the indexes 0 to n - 1. Asking for index n, here 7, is the usual result of a loop that tests i <= length instead of i < length.

  6. Question 6 of 19 What does this print?

    Read the code, then choose one answer.

    StringBuilder[] tags = {new StringBuilder("a"), new StringBuilder("b")};
    for (StringBuilder t : tags) {
        t.append("!");
        t = new StringBuilder("z");
    }
    IO.println(Arrays.toString(tags));
    Show the answer: Question 6 of 19

    Answer: [a!, b!]

    The loop variable t is a copy of each element, and each element is a reference. append changes the object that both the element and t refer to, so the array shows a! and b!. Assigning a new StringBuilder to t only redirects the copy; the array still holds the original two builders.

  7. Question 7 of 19 Marks.java finds who scored highest. Why does it keep best as an index instead of the mark itself?

    Choose one answer.

    Show the answer: Question 7 of 19

    Answer: names[best] needs the position, and a for-each loop gives only the values

    Keep a position whenever you need more than the value: here, the name at the same index of names. The run printed highest: 92 by Kabir (index 3).

  8. Question 8 of 19 Marks.java starts with best = 0 and prints marks[best] after the loop. What happens if marks is new int[0]?

    Choose one answer.

    Show the answer: Question 8 of 19

    Answer: marks[best] throws ArrayIndexOutOfBoundsException: Index 0 out of bounds for length 0

    best = 0 assumes at least one element. A method that may receive an empty array checks marks.length first, as the lesson says, and returns or reports something else.

  9. Question 9 of 19 Which expression gives the text [71, 64, 88] for int[] marks = {71, 64, 88};?

    Choose one answer.

    Show the answer: Question 9 of 19

    Answer: Arrays.toString(marks)

    Only Arrays.toString looks inside the array. Every other route goes through the toString that arrays inherit from Object, which names the class and gives a hash code.

  10. Question 10 of 19 A log line reads scores: [I@6d06d69c. What is the likely cause in the code that wrote it?

    Choose one answer.

    Show the answer: Question 10 of 19

    Answer: It joined the int[] itself, "scores: " + scores, instead of Arrays.toString(scores)

    Text such as [I@6d06d69c means an array met string concatenation or println without Arrays.toString. The fix is "scores: " + Arrays.toString(scores).

  11. Question 11 of 19 Which lines give copy an independent copy of the int[] a? Choose every one that does.

    Choose every answer that is right.

    Show the answer: Question 11 of 19

    Answer:

    • int[] copy = Arrays.copyOf(a, a.length);
    • int[] copy = new int[a.length]; System.arraycopy(a, 0, copy, 0, a.length);
    • int[] copy = a.clone();

    clone(), Arrays.copyOf and System.arraycopy into a new array all create a second array with the same values. int[] copy = a only copies the reference, and new int[a.length] on its own is a new array of zeros.

  12. Question 12 of 19 int[] a = {1, 2}; and int[] b = {1, 2}; What is a == b?

    Choose one answer.

    Show the answer: Question 12 of 19

    Answer: false

    == compares references. Two arrays with equal elements are still two objects, so a == b is false, while Arrays.equals(a, b), from the next lesson, compares the elements.

  13. Question 13 of 19 What does this print?

    Read the code, then choose one answer.

    int[] a = {1, 2, 3};
    int[] b = a;
    a = new int[] {7, 8, 9};
    IO.println(b[0]);
    Show the answer: Question 13 of 19

    Answer: 1

    An assignment changes which object one variable refers to. It never changes the object, and never another variable, so b still reads 1 from the first array.

  14. Question 14 of 19 Why did addGrace(marks) change the marks that main printed?

    Choose one answer.

    Show the answer: Question 14 of 19

    Answer: Its parameter received a copy of the reference, so it wrote into main's array

    Java passes every argument by value, and the value of an array variable is a reference. A method can therefore change the elements of the caller's array, but never which array the caller's variable refers to.

  15. Question 15 of 19 Which body of int[] plusTwo(int[] a) returns the marks plus 2 and leaves the caller's array as it was?

    Choose one answer.

    Show the answer: Question 15 of 19

    Answer: int[] r = a.clone(); for (int i = 0; i < r.length; i++) r[i] += 2; return r;

    Copy first, change the copy, return it. Only clone(), Arrays.copyOf or System.arraycopy into a new array gives a method elements of its own.

  16. Question 16 of 19 What does main print?

    Read the code, then choose one answer.

    void swap(int[] x, int[] y) {
        int[] t = x;
        x = y;
        y = t;
    }
    
    void main() {
        int[] p = {1};
        int[] q = {2};
        swap(p, q);
        IO.println(p[0] + " " + q[0]);
    }
    Show the answer: Question 16 of 19

    Answer: 1 2

    Like replace, swap only moves the method's own copies of the references. To swap the contents, a method would have to store into the arrays, for example int t = x[0]; x[0] = y[0]; y[0] = t;.

  17. Question 17 of 19 Why does Object[] things = new String[2]; compile?

    Choose one answer.

    Show the answer: Question 17 of 19

    Answer: Arrays are covariant, so a String[] is also an Object[]

    Covariance lets a method accept any array of objects. The cost is the store check: the JVM must check every store into an array of references while the program runs.

  18. Question 18 of 19 What happens with these two lines?

    Read the code, then choose one answer.

    Object[] things = new String[2];
    things[0] = 42;
    Show the answer: Question 18 of 19

    Answer: They compile, and the second line throws ArrayStoreException

    A String[] can be assigned to an Object[] variable, so the compiler only checks that 42 is an Object. The array itself is still a String[], and the JVM checks every store into an array of references, so storing an Integer throws ArrayStoreException.

  19. Question 19 of 19 What does List<Object> things = new ArrayList<String>(); do?

    Choose one answer.

    Show the answer: Question 19 of 19

    Answer: It does not compile, because a List<String> is not a List<Object>

    Unlike arrays, generic types are not covariant, so the mistake that StoreCheck.java makes at run time is caught by the compiler for lists. This is one reason later modules prefer collections in method parameters.

Interview questions

Fresher · What does int[] b = a; do in Java, and how do you get an independent copy of an int array?

It copies the reference, not the array. After the assignment, a and b refer to the same array object, so b[0] = 9 is visible through a, and a == b is true. To get an independent copy, create a new array with the same elements: a.clone(), Arrays.copyOf(a, a.length), which can also make the copy longer or shorter, or System.arraycopy into an array you created yourself. For an array of primitives such as int[], each of these is a complete copy. For an array of objects, each copies only the references, so the copy and the original share the objects themselves. A good answer also says how to check the result: a == copy is false, while Arrays.equals(a, copy) is true.

Interviewers often follow this answer with copies of arrays of objects. Work out what each snippet does before you look at the reasons:

Checkpoint

Interview round: two follow-up questions

  1. Question 1 of 2 An interviewer asks what this prints, and why.

    Read the code, then choose one answer.

    StringBuilder[] a = {new StringBuilder("x")};
    StringBuilder[] b = a.clone();
    b[0].append("y");
    IO.println(a[0] + " " + (a == b));
    Show the answer: Question 1 of 2

    Answer: xy false

    A copy of an array of objects copies the references, so the copy and the original share the objects. That is a shallow copy: right for an int[], and a trap when the objects can change, as a StringBuilder can.

  2. Question 2 of 2 String[] copy = names.clone(); is followed by copy[0] = "Ravi";. What does names[0] hold now?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: Its old string, because the store changed only the copy

    Replacing an element affects only the array you store into; changing a shared object shows through both arrays. Strings can never change, so sharing them is harmless, which makes a shallow copy of a String[] as good as a full one.

This lesson is also the starting point of two longer questions in the module bank: a helper that sorts the array it was given, and a library method that throws ArrayStoreException for one caller only.

Model answers open with any pass: ₹79 for 1 week ($2.99), one payment that never renews.

  1. Fresher to mid

    A helper median(int[] scores) sorts its argument to find the middle value. After a release, a leaderboard that calls it shows the scores in ascending order instead of the order players finished. Explain the bug, fix it, and say what your fix costs for 10 million scores.

    Model answer, Pro. Model answers open with any pass; prices are in the notice on this page. First step and follow-ups

  2. Mid to senior

    A library method fillDefaults(Object[] slots, Object value) passes its tests, but in production one caller gets ArrayStoreException. Why can the compiler not catch this, how do you find the caller, and how would you change the API so that the mistake no longer compiles?

    Model answer, Pro. First step and follow-ups

Key takeaways

  • An array has a fixed length, set by new int[n] or counted from an initialiser such as {71, 64, 88}, and every new element starts at its type’s default: 0, 0.0, false, the character with code 0, or null.
  • Indexes run from 0 to length - 1, and the JVM checks every access: a loop with i <= a.length throws ArrayIndexOutOfBoundsException on its extra pass, and the message names the index and the length.
  • for-each reads every value with no index to get wrong; its variable is a copy of each element, so it can change the objects an array refers to but never replace an element, which takes an indexed loop.
  • Printing an array shows its class name and a hash code, such as [I@ and hexadecimal digits; Arrays.toString shows the elements.
  • An array variable holds a reference: b = a shares one array, == compares references, clone(), Arrays.copyOf and System.arraycopy copy the elements, and a method can change the elements of an array it receives, so copy first when it must not.
  • Because a String[] is also an Object[], storing a value of the wrong type compiles and then throws ArrayStoreException.

Terms in this lesson

alias
A second name for the same object: after int[] b = a; both variables refer to one array, so a change made through either is seen through the other, and a == b is true.
array covariance
The rule that an array of a subtype is also an array of its supertype, so a String[] may be assigned to an Object[]. The JVM then checks every store into an array of references while the program runs and throws ArrayStoreException for a value of the wrong type.
default value
The value every element of a new array starts with, before anything is stored in it: 0 for the integer types, 0.0 for float and double, false for boolean, the character with code 0 for char, and null for every reference type.
parallel arrays
Two or more arrays kept in step by index, such as names[i] and marks[i] for one student. Sorting or changing one of them without the others breaks the link, which is why one array of records is usually safer.

References

Related tools

Report a problem with this lesson

Quick answers and tool search

Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.