This sets the type of a, as array of arrays :
String[][] a
When you write
String[][] a = new String[10][];
you initialize the external array, but you don't create the internal arrays, so that a[0] is null.
When you write
String[][] b = new String[10][10];
the runtime creates also the internal arrays. It's described here in the specification :
At run time, evaluation of an array creation expression behaves as
follows:
If there are no dimension expressions, then there must be an array
initializer.
A newly allocated array will be initialized with the values provided
by the array initializer as described in §10.6.
The value of the array initializer becomes the value of the array
creation expression.
Otherwise, there is no array initializer, and:
First, the dimension expressions are evaluated, left-to-right. If any
of the expression evaluations completes abruptly, the expressions to
the right of it are not evaluated.
Next, the values of the dimension expressions are checked. If the
value of any DimExpr expression is less than zero, then a
NegativeArraySizeException is thrown.
Next, space is allocated for the new array. If there is insufficient
space to allocate the array, evaluation of the array creation
expression completes abruptly by throwing an OutOfMemoryError.
Then, if a single DimExpr appears, a one-dimensional array is created
of the specified length, and each component of the array is
initialized to its default value (§4.12.5).
Otherwise, if n DimExpr expressions appear, then array creation
effectively executes a set of nested loops of depth n-1 to create the
implied arrays of arrays.
A multidimensional array need not have arrays of the same length at
each level.