Arrays

This section documents the current Java release line, with Java 25 LTS as the reference point (no specific patch version is pinned), as published at the Java developer portal, the Java Tutorials, and the Java SE API specification — which are the references these pages are written and verified against.

This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production.

This section’s bibliography lists the reference material consulted while preparing these pages.

An array is a fixed-length, indexed container whose elements all share one type. Arrays are the lowest-level aggregate in Java; higher-level structures live in the Collections Framework. This page follows the dev.java "Creating Arrays in Your Programs" track and the Java Tutorials on arrays; the normative rules are in JLS chapter 10 ("Arrays").

Declaring, Allocating, and Initializing

The type is written elementType[]. Declaring a variable does not create an array; new allocates one of a chosen length, which is then fixed for the array’s life. Every element starts at its type’s default: 0 for integral types, 0.0 for floating-point, false for boolean, the null character (code point 0) for char, and null for any reference type.

int[] counts = new int[4];         // {0, 0, 0, 0}
counts[0] = 10;
counts[3] = 40;
// counts[4] = 50;                  // ArrayIndexOutOfBoundsException at run time

String[] names = new String[2];    // {null, null}

int[] primes = {2, 3, 5, 7, 11};   // array literal: length inferred from the elements
var more   = new int[] {13, 17};   // long form: required outside a declaration (e.g. an argument)

System.out.println(primes.length); // 5  -- a final field, not a method call
System.out.println(primes[0]);     // 2  -- indices run 0 .. length-1

length is a final field, not a method. Any index outside 0 .. length-1 throws ArrayIndexOutOfBoundsException, and a negative size in new int[n] throws NegativeArraySizeException. The C-style form int counts[] compiles but is discouraged — keep the brackets on the type.

Iterating

Use an indexed for when you need the position or must write elements back; use the enhanced for when you only read each element.

int[] xs = {4, 8, 15, 16, 23, 42};

for (int i = 0; i < xs.length; i++) {
    xs[i] *= 2;                     // index needed: writing back
}

long total = 0;
for (int x : xs) {
    total += x;                     // read-only: enhanced for is clearer
}
System.out.println(total);         // 236

Covariance and Reification

Arrays are covariant: String[] is a subtype of Object[]. They are also reified — an array carries its element type at run time and rejects a wrong-typed store with ArrayStoreException.

Object[] objs = new String[3];     // legal: covariance
objs[0] = "ok";
objs[1] = 42;                      // compiles, but throws ArrayStoreException at run time

Generics behave the opposite way: List<String> is not a List<Object>, and type arguments are erased at run time rather than reified. That mismatch is why new T[] is illegal in a generic class and why mixing arrays with generics is discouraged — see Generics.

Multidimensional and Jagged Arrays

Java has no true rectangular arrays; int[][] is an array whose elements are themselves int[]. A rectangular shape is merely the common case — rows can have different lengths, giving a jagged array.

int[][] matrix = {
    {1, 2, 3},
    {4, 5, 6}
};
System.out.println(matrix[1][2]);      // 6
System.out.println(matrix.length);     // 2  (number of rows)
System.out.println(matrix[0].length);  // 3  (columns in row 0)

int[][] triangle = new int[3][];       // rows allocated, columns not yet
triangle[0] = new int[] {1};
triangle[1] = new int[] {1, 1};
triangle[2] = new int[] {1, 2, 1};

for (int[] row : triangle) {
    System.out.println(java.util.Arrays.toString(row));
}

java.util.Arrays and varargs

java.util.Arrays supplies the everyday array algorithms. Use Arrays.toString / Arrays.deepToString for printing (a bare array’s inherited toString is the useless [I@1b6d3586), and Arrays.equals / Arrays.deepEquals for value comparison (== only compares references).

import java.util.Arrays;

int[] a = {5, 2, 9, 1, 7};
Arrays.sort(a);                              // {1, 2, 5, 7, 9}  (in place)
int at = Arrays.binarySearch(a, 7);         // 3   -- array MUST already be sorted
int[] grown = Arrays.copyOf(a, 7);          // {1, 2, 5, 7, 9, 0, 0}
int[] slice = Arrays.copyOfRange(a, 1, 4);  // {2, 5, 7}

int[] flags = new int[3];
Arrays.fill(flags, -1);                      // {-1, -1, -1}

System.out.println(Arrays.toString(a));      // [1, 2, 5, 7, 9]
System.out.println(Arrays.equals(a, grown)); // false

int[][] m1 = {{1, 2}, {3, 4}};
int[][] m2 = {{1, 2}, {3, 4}};
System.out.println(Arrays.deepEquals(m1, m2));   // true
System.out.println(Arrays.deepToString(m1));     // [[1, 2], [3, 4]]

int sum = Arrays.stream(a).sum();           // 24   -- an IntStream over the array
var view = Arrays.asList("x", "y", "z");    // fixed-size List backed by the array

Arrays.asList returns a fixed-size list view: set works, but add/remove throw UnsupportedOperationException. For a growable copy use new ArrayList<>(Arrays.asList(…​)); for an immutable one use List.of(…​).

jshell> int[] xs = {1, 2, 3}
xs ==> int[3] { 1, 2, 3 }

jshell> xs.toString()
$2 ==> "[I@2f0e140b"

jshell> java.util.Arrays.toString(xs)
$3 ==> "[1, 2, 3]"

A varargs parameter (Type…​ name) is an array on the callee side; the compiler packs the call arguments into a fresh array. main receives the program arguments the same way. See Arbitrary Number of Arguments.

static int maxOf(int first, int... rest) {   // 'rest' is an int[]
    int m = first;
    for (int v : rest) {
        m = Math.max(m, v);
    }
    return m;
}

maxOf(3);                 // rest.length == 0
maxOf(3, 9, 2, 7);        // rest == {9, 2, 7}
int[] data = {4, 5, 6};
maxOf(1, data);           // an existing array passes straight through

public static void main(String[] args) {     // java Launcher alpha beta -> args == {"alpha", "beta"}
    for (String arg : args) {
        System.out.println(arg);
    }
}

Passing an explicit null to a varargs method makes rest itself null, not empty — cast it (maxOf(1, (int[]) null)) only if that is genuinely what you mean.

See Also