2D Array Creation and Access

A 2D array holds values in rows and columns. Java stores one as an array of arrays, so it's created and indexed the way a 1D array is, twice over. The arrays below describe a parking garage with 3 levels of 5 spaces each.
Creating one with new
String[][] plates = new String[3][5];
The first number gives the rows and the second gives the columns, so plates has 3 rows of 5, or 15 elements. Each row is one level of the garage.
Every element starts at the default for its type. A String is a reference type, so all 15 elements start as null, meaning no car is parked there yet. An int[][] would start full of 0, a double[][] full of 0.0, and a boolean[][] full of false.
An initializer list
The number of hours each car has been parked can be written directly.
int[][] hours = { {2, 0, 5, 1, 3},
{0, 4, 4, 0, 6},
{1, 1, 0, 2, 0} };
A 2D initializer list is a list of 1D initializer lists, one per row. Three inner lists make three rows, and five values in each make five columns.
Accessing an element
Two pairs of brackets name one element, the row first and then the column.
hours[1][4] = hours[1][4] + 1;
plates[2][2] = "BX4 2210";
The first statement reads 6 from row 1, column 4, and stores 7 there. The second records a car that just parked in the third space of level 2, where hours still shows 0. Both indexes count from 0, so hours[1][4] is the second row and the fifth column. Swapping the indexes names a different element, and hours[4][1] would throw, since there's no row 4.
Rows and lengths
One index names a whole row. hours[2] is the 1D array holding 1, 1, 0, 2, and 0, the hours on level 2. So hours[2][3] can be read as element 3 of that row, which is 2.
That gives the two sizes. hours.length counts the rows. It's 3, since the outer array holds one element per row. hours[0].length counts the elements in row 0, and that's how many columns there are, 5.