Java Multidimensional Arrays — 2D Arrays, Jagged Arrays & More
A multidimensional array is an array of arrays. The most common is the 2D array — perfect for representing tables, grids, matrices, and game boards.
Declaring and Creating 2D Arrays
// Declare and create a 3×4 matrix (3 rows, 4 columns)
int[][] matrix = new int[3][4];
This creates a grid with 3 rows and 4 columns, all initialised to 0.
Initialise with Values
int[][] grid = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
Access Elements
System.out.println(grid[0][0]); // 1 (row 0, col 0)
System.out.println(grid[1][2]); // 6 (row 1, col 2)
System.out.println(grid[2][1]); // 8 (row 2, col 1)
Dimensions
int rows = grid.length; // 3
int cols = grid[0].length; // 3
Iterating Over a 2D Array
Nested for Loops
for (int i = 0; i < grid.length; i++) {
for (int j = 0; j < grid[i].length; j++) {
System.out.printf("%3d", grid[i][j]);
}
System.out.println();
}
Output:
1 2 3
4 5 6
7 8 9
Enhanced for-each
for (int[] row : grid) {
for (int val : row) {
System.out.printf("%3d", val);
}
System.out.println();
}
Jagged Arrays (Ragged Arrays)
In Java, each row can have a different number of columns:
int[][] jagged = new int[3][];
jagged[0] = new int[]{1, 2};
jagged[1] = new int[]{3, 4, 5, 6};
jagged[2] = new int[]{7};
Row 0: [1, 2]
Row 1: [3, 4, 5, 6]
Row 2: [7]
Always use jagged[i].length — not a fixed column count — when iterating:
for (int i = 0; i < jagged.length; i++) {
for (int j = 0; j < jagged[i].length; j++) {
System.out.print(jagged[i][j] + " ");
}
System.out.println();
}
Memory Layout
A 2D array in Java is not a single contiguous block (unlike C). It is an array of references to row arrays:
matrix ──→ [ ref0, ref1, ref2 ]
│ │ │
▼ ▼ ▼
[1,2,3] [4,5,6] [7,8,9]
Each row is a separate object on the heap, which is why jagged arrays are possible.
Practical Example 1 — Matrix Addition
public static int[][] add(int[][] a, int[][] b) {
int rows = a.length;
int cols = a[0].length;
int[][] result = new int[rows][cols];
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
result[i][j] = a[i][j] + b[i][j];
}
}
return result;
}
Practical Example 2 — Matrix Transpose
public static int[][] transpose(int[][] matrix) {
int rows = matrix.length;
int cols = matrix[0].length;
int[][] result = new int[cols][rows];
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
result[j][i] = matrix[i][j];
}
}
return result;
}
Practical Example 3 — Tic-Tac-Toe Board
public class TicTacToe {
private char[][] board = {
{' ', ' ', ' '},
{' ', ' ', ' '},
{' ', ' ', ' '}
};
public void place(int row, int col, char symbol) {
if (board[row][col] != ' ') {
throw new IllegalStateException("Cell already taken");
}
board[row][col] = symbol;
}
public void print() {
for (int i = 0; i < 3; i++) {
System.out.printf(" %c | %c | %c %n",
board[i][0], board[i][1], board[i][2]);
if (i < 2) System.out.println("---+---+---");
}
}
}
Practical Example 4 — Student Grade Matrix
String[] students = {"Alice", "Bob", "Charlie"};
int[][] grades = {
{90, 85, 92}, // Alice: Math, Science, English
{78, 88, 95}, // Bob
{85, 90, 80} // Charlie
};
for (int i = 0; i < students.length; i++) {
int sum = 0;
for (int g : grades[i]) sum += g;
double avg = (double) sum / grades[i].length;
System.out.printf("%s → Average: %.1f%n", students[i], avg);
}
3D Arrays and Beyond
int[][][] cube = new int[3][3][3];
cube[0][1][2] = 42;
3D arrays are rare in practice. If you find yourself using them, consider whether a List<List<List<T>>> or a custom class would be clearer.
Common Mistakes
| Mistake | Problem | Fix |
|---|---|---|
Using matrix.length for columns |
Gives row count | Use matrix[0].length |
| Assuming rectangular shape | Jagged arrays break this | Check each row.length |
| Off-by-one in nested loops | ArrayIndexOutOfBoundsException |
Use < length, not <= |
Printing with toString() |
Shows references, not values | Use Arrays.deepToString() |
Key Takeaways
- A 2D array is an array of arrays — each row is a separate object on the heap.
- Jagged arrays allow rows of different lengths.
- Use nested loops or
for-eachto traverse. - Use
Arrays.deepToString()andArrays.deepEquals()for printing and comparing. - For most real-world work, prefer
List<List<T>>unless performance demands arrays.
What’s Next?
We leave arrays behind and dive into Strings — Java’s most used class. You’ll learn about immutability, the String pool, and the critical difference between == and .equals().