Playing with multidimensional arrays and method references can be tricky sometimes.
1. Referencing Array’s Constructor
Let’s say we want to create a function that takes an integer value and returns an array with a size initialized to that value.
We can do that fairly easily using a Lambda Expression literal:
size -> new String[size]
but…what if we wanted to grant it its own name?
There’s a number of ways to do that. The two most natural ways would be to represent it either as a Function<Integer, String[]> or an IntFunction<String[]>:
IntFunction<String[]> foo1 = size -> new String[size]; Function<Integer, String[]> foo2 = size -> new String[size];
Since our logic is trivial and we’re just passing a raw parameter straight to the constructor, we might as well directly reference the array’s constructor to avoid boilerplate:
IntFunction<String[]> foo1 = String[]::new;
2. Referencing Multidimensional Array’s Constructor
Why not do the same with a 2D array?
BiFunction<Integer, Integer, String[][]> foo2D = (rows, cols) -> new String[rows][cols]; BiFunction<Integer, Integer, String[][]> foo2D2 = String[][]::new; // compilation error
Unfortunately, the Method Reference approach leaves us with a compilation error. Do you already have an idea why?
Since multidimensional arrays in Java aren’t really multidimensional (they’re just arrays of arrays), when writing String[][]::new, we’re still referencing exactly same one-parameter constructor as in the first example:
IntFunction<String[]> foo1 = String[]::new;
It’s just the type that array stores isn’t String anymore but String[]:
IntFunction<String[]> foo1 = String[]::new;
IntFunction<String[][]> foo2 = String[][]::new;
Essentially, both cases could be represented as a generic IntFunction<T[]>.
Hopefully, everything becomes clear if we look at the standard Lambda Expression equivalent of the second example:
IntFunction<String[][]> foo1 = size -> new String[size][];
This short write-up was sponsored by this StackOverflow question.