Multidimensional Arrays
A multidimensional array is simply an array whose elements are themselves arrays. Java does not have true matrix types, but by nesting arrays you can represent grids, tables, and higher-dimensional data structures naturally. The most common case by far is the 2D array, used for things like matrices, game boards, and spreadsheet data.
Declaring a 2D Array
In Java, the syntax for a two-dimensional array is type[][]. You can put the brackets after the type or after the variable name — the first style is preferred.
int[][] matrix; // preferred
int matrix2[][]; // legal but less readable
Note: The declaration above only creates a reference variable. No array object exists yet and no memory is allocated until you use
newor an initializer.
Creating and Initializing a 2D Array
Using new
public class Create2D {
public static void main(String[] args) {
// Create a 3-row, 4-column int array (all elements default to 0)
int[][] grid = new int[3][4];
// Assign values
grid[0][0] = 1;
grid[1][2] = 7;
grid[2][3] = 99;
System.out.println(grid[1][2]); // 7
System.out.println(grid[0][1]); // 0 (default)
}
}
Output:
7
0
Using an Array Literal
When you already know the values at compile time, use the initializer syntax:
public class LiteralInit {
public static void main(String[] args) {
int[][] scores = {
{85, 90, 78},
{92, 88, 95},
{70, 65, 80}
};
System.out.println(scores[1][2]); // row 1, column 2 → 95
}
}
Output:
95
Accessing Elements
You index into a 2D array with two index expressions: array[row][col]. Both indices are zero-based.
public class Access2D {
public static void main(String[] args) {
int[][] table = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
// Read a single element
System.out.println("Center: " + table[1][1]); // 5
// Replace an element
table[2][0] = 100;
System.out.println("Updated: " + table[2][0]); // 100
}
}
Output:
Center: 5
Updated: 100
Iterating Over a 2D Array
Nested for Loop
The classic approach — outer loop over rows, inner loop over columns.
public class Iterate2D {
public static void main(String[] args) {
int[][] matrix = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
for (int row = 0; row < matrix.length; row++) {
for (int col = 0; col < matrix[row].length; col++) {
System.out.printf("%3d", matrix[row][col]);
}
System.out.println();
}
}
}
Output:
1 2 3
4 5 6
7 8 9
Enhanced for-each Loop
The for-each loop keeps the code clean when you only need to read values.
public class ForEach2D {
public static void main(String[] args) {
String[][] names = {
{"Alice", "Bob"},
{"Carol", "Dave"}
};
for (String[] row : names) {
for (String name : row) {
System.out.print(name + " ");
}
System.out.println();
}
}
}
Output:
Alice Bob
Carol Dave
Array Length in 2D Arrays
matrix.length gives you the number of rows. matrix[i].length gives the number of columns in row i (which may differ for jagged arrays).
int[][] grid = new int[3][5];
System.out.println(grid.length); // 3 (rows)
System.out.println(grid[0].length); // 5 (columns in row 0)
See the Array length page for a detailed look at the length property.
3D Arrays (and Beyond)
You can add more dimensions by adding more bracket pairs. A 3D array is an array of 2D arrays.
public class ThreeDArray {
public static void main(String[] args) {
// Think of it as 2 layers, each 3 rows × 4 columns
int[][][] cube = new int[2][3][4];
cube[0][1][2] = 42;
cube[1][2][3] = 99;
System.out.println(cube[0][1][2]); // 42
System.out.println(cube[1][2][3]); // 99
}
}
Output:
42
99
Tip: Beyond 3D, code becomes hard to reason about. If you find yourself needing 4+ dimensions, consider a flat array with index arithmetic or a dedicated data structure instead.
Practical Example: Matrix Multiplication
A classic algorithm that shows 2D arrays in action.
public class MatrixMultiply {
public static void main(String[] args) {
int[][] a = {{1, 2}, {3, 4}};
int[][] b = {{5, 6}, {7, 8}};
int rows = a.length;
int cols = b[0].length;
int inner = b.length;
int[][] result = new int[rows][cols];
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
for (int k = 0; k < inner; k++) {
result[i][j] += a[i][k] * b[k][j];
}
}
}
// Print result
for (int[] row : result) {
for (int val : row) {
System.out.printf("%4d", val);
}
System.out.println();
}
}
}
Output:
19 22
43 50
Jagged Arrays (Non-Rectangular)
Because Java’s multidimensional arrays are truly arrays of arrays, each row can have a different length. These are called jagged arrays (or ragged arrays).
public class JaggedArray {
public static void main(String[] args) {
// Allocate only the outer array
int[][] triangle = new int[4][];
// Allocate each row individually with different sizes
for (int i = 0; i < triangle.length; i++) {
triangle[i] = new int[i + 1];
for (int j = 0; j <= i; j++) {
triangle[i][j] = i + j;
}
}
// Print
for (int[] row : triangle) {
for (int val : row) {
System.out.print(val + " ");
}
System.out.println();
}
}
}
Output:
0
1 2
2 3 4
3 4 5 6
Note: When you omit the column size (
new int[4][]), Java creates an outer array whose elements arenull. You must allocate each inner array yourself before accessing it, otherwise you’ll get aNullPointerException.
See the Jagged Arrays page for an in-depth treatment.
Common Mistakes
| Mistake | What happens | Fix |
|---|---|---|
array[row][col] with out-of-bounds index | ArrayIndexOutOfBoundsException at runtime | Check row < array.length and col < array[row].length |
Using array.length for column count on a jagged array | Wrong count for rows that differ | Use array[row].length per row |
| Forgetting to allocate inner arrays in a jagged array | NullPointerException when accessing elements | Initialize each array[i] with new type[size] |
Comparing arrays with == | Compares references, not contents | Use Arrays.deepEquals(a, b) |
Under the Hood
Memory Layout: Arrays of Arrays
Java does not store 2D array elements in a single contiguous block of memory the way C does. Instead, a int[3][4] allocates:
- 1 outer array object holding 3 references (one per row).
- 3 inner array objects, each holding 4
intvalues.
This means each inner array is a separate heap object, and dereferencing matrix[row][col] involves two pointer dereferences (outer reference → inner array header → element). For large matrices where cache performance matters, this indirection can be slower than a flat 1D array with manual index arithmetic (array[row * cols + col]).
// Cache-friendly alternative for performance-critical code
int rows = 1000, cols = 1000;
int[] flat = new int[rows * cols];
flat[5 * cols + 7] = 42; // equivalent to [5][7]
Object Headers
Every inner array is a full Java object: it carries a 12-byte object header (mark word + class pointer on 64-bit JVM with compressed oops) plus 4 bytes for the length field. So a new int[3][4] is 4 separate objects with total overhead of 4 × 16 bytes = 64 bytes of header before any element data.
Arrays.deepToString and Arrays.deepEquals
The standard library provides helper methods specifically for multidimensional arrays — the regular Arrays.toString only prints the outer array’s references.
import java.util.Arrays;
public class DeepPrint {
public static void main(String[] args) {
int[][] m = {{1, 2}, {3, 4}};
System.out.println(Arrays.toString(m)); // [[I@..., [I@...]
System.out.println(Arrays.deepToString(m)); // [[1, 2], [3, 4]]
int[][] copy = {{1, 2}, {3, 4}};
System.out.println(Arrays.equals(m, copy)); // false (reference compare)
System.out.println(Arrays.deepEquals(m, copy)); // true (deep compare)
}
}
Output:
[[I@6d06d69c, [I@7852e922]
[[1, 2], [3, 4]]
false
true
See the Arrays Utility Class page for the full list of helpers.
Related Topics
- Arrays — single-dimensional arrays, the building block of multidimensional arrays
- Jagged Arrays — non-rectangular arrays where each row has a different length
- Arrays Utility Class —
deepToString,deepEquals,fill, and sorting helpers - for-each Loop — clean iteration over rows and elements without index variables
- Array length — understanding the
lengthproperty and how it works per dimension - Array of Objects — storing objects (not just primitives) in 2D arrays