Array Length
Every Java array knows how many elements it holds, available through its length field. The length is set when the array is created and can never change. Using length correctly is what keeps loops within bounds, makes code work for arrays of any size, and avoids the most common array error, ArrayIndexOutOfBoundsException.
Reading the Length
int[] scores = {72, 85, 90, 64};
String[] empty = new String[0];
double[] buffer = new double[1024];
System.out.println(scores.length); // 4
System.out.println(empty.length); // 0
System.out.println(buffer.length); // 1024
length is a field, not a method, so it has no parentheses. It is final: assigning to it does not compile.
scores.length = 10; // compile error: cannot assign a value to final variable length
length reports the capacity of the array: the number of slots, not the number of slots you have filled with meaningful values. new int[5] has length 5 even though every element is 0.
length, length(), and size()
Three similar names are easy to mix up:
| Type | How to get the count | Kind |
|---|---|---|
Array (int[], String[], ...) | arr.length | Field |
String | str.length() | Method |
Collection (List, Set, Map) | list.size() | Method |
String[] words = {"java", "bash"};
System.out.println(words.length); // 2: number of strings in the array
System.out.println(words[0].length()); // 4: number of characters in "java"
List<String> list = List.of("a", "b", "c");
System.out.println(list.size()); // 3
The inconsistency is historical: arrays are built into the language, while String and collections are ordinary classes with methods.
Indexes Run from 0 to length − 1
An array of length n has valid indexes 0 through n - 1:
length = 5
index: 0 1 2 3 4
[ a ][ b ][ c ][ d ][ e ]
└── last index = length - 1
char[] letters = {'a', 'b', 'c', 'd', 'e'};
char first = letters[0];
char last = letters[letters.length - 1]; // 'e'
char middle = letters[letters.length / 2]; // 'c'
Using letters[letters.length] is a classic off-by-one error:
java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 5
The exception message states both the attempted index and the actual length, which usually points directly at the bug.
Using length in Loops
Writing length in the loop condition, rather than a hard-coded number, keeps the loop correct for any array:
int[] values = {4, 8, 15, 16, 23, 42};
int sum = 0;
for (int i = 0; i < values.length; i++) { // < , not <=
sum += values[i];
}
System.out.println(sum); // 108
| Pattern | Covers |
|---|---|
for (int i = 0; i < a.length; i++) | Every index, forward |
for (int i = a.length - 1; i >= 0; i--) | Every index, backward |
for (int i = 1; i < a.length; i++) | Every index except the first (for comparing with a[i - 1]) |
for (int i = 0; i < a.length - 1; i++) | Every index except the last (for comparing with a[i + 1]) |
The last two forms are used when each step looks at a neighbor. Getting the bound right ensures the neighbor index stays valid.
Empty Arrays
An array of length 0 is legal and useful. It represents "no elements" without using null:
int[] none = new int[0];
int[] alsoNone = {};
for (int v : none) {
System.out.println(v); // never runs
}
System.out.println(none.length); // 0
Code that loops using length handles empty arrays automatically. Code that reads a[0] without checking does not:
static int max(int[] a) {
if (a.length == 0) {
throw new IllegalArgumentException("array is empty");
}
int m = a[0];
for (int i = 1; i < a.length; i++) m = Math.max(m, a[i]);
return m;
}
Methods that return arrays should return an empty array rather than null when there is nothing to return. Callers can then loop over the result without a null check:
static String[] tagsFor(String post) {
if (post.isBlank()) {
return new String[0];
}
return post.split("\\s+");
}
null versus empty
null means there is no array at all. Reading length on it throws:
int[] data = null;
System.out.println(data.length); // NullPointerException
Check for null first when an array may be absent: if (data == null || data.length == 0).
The Length Is Fixed
An array cannot grow or shrink. "Resizing" means creating a new array and copying the elements:
import java.util.Arrays;
int[] small = {1, 2, 3};
int[] larger = Arrays.copyOf(small, 6); // [1, 2, 3, 0, 0, 0]
int[] shorter = Arrays.copyOf(small, 2); // [1, 2]
small = Arrays.copyOf(small, small.length * 2); // reassign the variable to the new array
The original array object is unchanged; the variable now points to a different, larger array.
Tracking how many slots are used
When an array is used as a buffer, its length (capacity) and the number of meaningful elements (size) differ. Code must track the size separately:
public class IntBuffer {
private int[] data = new int[4];
private int size = 0; // how many slots are actually in use
public void add(int value) {
if (size == data.length) { // full: grow by doubling
data = Arrays.copyOf(data, data.length * 2);
}
data[size++] = value;
}
public int get(int index) {
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException("Index " + index + ", size " + size);
}
return data[index];
}
public int size() { return size; }
public int capacity() { return data.length; }
}
IntBuffer buf = new IntBuffer();
for (int i = 1; i <= 5; i++) buf.add(i * 10);
System.out.println(buf.size() + " / " + buf.capacity()); // 5 / 8
This is essentially how ArrayList works internally: an array with spare capacity, a separate size counter, and growth by copying when full. Doubling the capacity keeps the average cost of each add constant, because copies become increasingly rare as the array grows.
Length of Multidimensional Arrays
A two-dimensional array is an array of arrays. Its length is the number of rows; each row has its own length:
int[][] grid = new int[3][4];
System.out.println(grid.length); // 3: rows
System.out.println(grid[0].length); // 4: columns in row 0
Rows do not have to be the same length ("jagged" arrays):
int[][] triangle = {
{1},
{1, 1},
{1, 2, 1},
{1, 3, 3, 1}
};
for (int r = 0; r < triangle.length; r++) {
for (int c = 0; c < triangle[r].length; c++) { // use THIS row's length
System.out.print(triangle[r][c] + " ");
}
System.out.println();
}
Output:
1
1 1
1 2 1
1 3 3 1
Using triangle[0].length for every row would read past the end of the shorter rows. Always use arr[r].length for the inner loop.
Limits on Array Length
- The length is an
int, so the theoretical maximum isInteger.MAX_VALUE(about 2.1 billion). In practice the JVM reserves a few header slots, and very large arrays also require enough heap memory. - A negative length throws
NegativeArraySizeException. - Requesting more memory than the heap allows throws
OutOfMemoryError:
long[] huge = new long[500_000_000]; // needs about 4 GB; fails on a smaller heap
When reading a length from external input (a file header, a network message, a user), validate it before allocating, so a malformed or malicious value cannot make the program allocate an enormous array.
length with Varargs and main
Varargs parameters and main's args are ordinary arrays, so length tells you how many arguments were passed:
public static void main(String[] args) {
if (args.length < 2) {
System.err.println("Usage: java Copy <source> <target>");
System.exit(1);
}
System.out.println("Copying " + args[0] + " to " + args[1]);
}
static double average(double... values) {
if (values.length == 0) return 0;
double sum = 0;
for (double v : values) sum += v;
return sum / values.length;
}
Checking args.length before reading args[0] prevents an ArrayIndexOutOfBoundsException when the program is run without arguments.
Practical Example: Paginating Results
import java.util.Arrays;
public class Pager {
static String[] page(String[] items, int pageNumber, int pageSize) {
if (pageSize <= 0) throw new IllegalArgumentException("pageSize must be positive");
int totalPages = (items.length + pageSize - 1) / pageSize; // ceiling division
if (pageNumber < 1 || pageNumber > Math.max(totalPages, 1)) {
return new String[0];
}
int from = (pageNumber - 1) * pageSize;
int to = Math.min(from + pageSize, items.length); // last page may be short
return Arrays.copyOfRange(items, from, to);
}
public static void main(String[] args) {
String[] products = {"Pen", "Pencil", "Eraser", "Ruler", "Stapler", "Tape", "Glue"};
int size = 3;
int pages = (products.length + size - 1) / size;
for (int p = 1; p <= pages; p++) {
String[] onPage = page(products, p, size);
System.out.println("Page " + p + "/" + pages + " (" + onPage.length + " items): "
+ Arrays.toString(onPage));
}
System.out.println("Page 9: " + Arrays.toString(page(products, 9, size)));
}
}
Output:
Page 1/3 (3 items): [Pen, Pencil, Eraser]
Page 2/3 (3 items): [Ruler, Stapler, Tape]
Page 3/3 (1 items): [Glue]
Page 9: []
Every calculation is driven by items.length. Ceiling division gives the number of pages, so 7 items in pages of 3 need 3 pages. Math.min(from + pageSize, items.length) keeps the last page from running past the end of the array, which is why page 3 contains only one item. An out-of-range page returns an empty array, not null, so the caller can print or loop over it safely. The same arithmetic underlies pagination in web applications and database queries.