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
-
Collections Framework —
List,Set,Map, and when to prefer them over raw arrays. -
Generics — type erasure, and why arrays and generics mix poorly.
-
Control Flow — the indexed and enhanced
forin detail. -
Streams and Collectors —
Arrays.streamand bulk data processing.