Skip to content
Java arrays 6 min read

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 new or 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 are null. You must allocate each inner array yourself before accessing it, otherwise you’ll get a NullPointerException.

See the Jagged Arrays page for an in-depth treatment.


Common Mistakes

MistakeWhat happensFix
array[row][col] with out-of-bounds indexArrayIndexOutOfBoundsException at runtimeCheck row < array.length and col < array[row].length
Using array.length for column count on a jagged arrayWrong count for rows that differUse array[row].length per row
Forgetting to allocate inner arrays in a jagged arrayNullPointerException when accessing elementsInitialize each array[i] with new type[size]
Comparing arrays with ==Compares references, not contentsUse 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 int values.

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.


  • Arrays — single-dimensional arrays, the building block of multidimensional arrays
  • Jagged Arrays — non-rectangular arrays where each row has a different length
  • Arrays Utility ClassdeepToString, deepEquals, fill, and sorting helpers
  • for-each Loop — clean iteration over rows and elements without index variables
  • Array length — understanding the length property and how it works per dimension
  • Array of Objects — storing objects (not just primitives) in 2D arrays
Last updated June 13, 2026
Was this helpful?