In Java we may create IntFunction<String[]> from 1D array constructor reference:
    // both do the same thing
    IntFunction<String[]> createArrayL = size -> new String[size];
    IntFunction<String[]> createArrayMR = String[]::new;
Now I wonder why we cannot do this with a 2D array:
    BiFunction<Integer, Integer, String[][]> createArray2DL = 
            (rows, cols) -> new String[rows][cols];
    // error:
    BiFunction<Integer, Integer, String[][]> createArray2DMR =
            String[][]::new;
Of course we may write:
    IntFunction<String[][]> createArray2DInvalidL = String[][]::new;
    System.out.println(createArray2DInvalidL.apply(3)[0]); // prints null
but this will behave differently than:
    new String[3][3]
because row arrays will not be initialized.
So my question is: why String[][]::new doesn't work for 2D arrays (for me it looks like an inconsistency in language design)?
Quite an interesting case indeed.
The problem is that String[][]::new is a function with an arity of 1(it's a constructor of an array of arrays) and can't be treated as a BiFunction(arity of 2) and your example new String[3][3] has two parameters instead of one. 
In this case,
createArray2DInvalidL.apply(3)
is equal to calling new String[3][];
What you might be looking for is:
IntFunction<String[][]> createArray2D = n -> new String[n][n];
Dimensions don't need to have equal lengths and it sounds like a pretty reasonable assumption.
http://4comprehension.com/multidimensional-arrays-vs-method-references/
There is no inconsistency here. If you write a statement like
IntFunction<ElementType[]> f = ElementType[]::new;
you create a function whose evaluation will return a new array with each entry being capable of holding a reference of ElementType, initialized to null. This doesn’t change, when you use String[] for ElementType.
But it also has been addressed explicitly in The Java Language Specification, §15.13.3. Run-Time Evaluation of Method References:
If the form is Type[]k :: new (k ≥ 1), then the body of the invocation method has the same effect as an array creation expression of the form new Type [ size ] []k-1, where size is the invocation method’s single parameter. (The notation []k indicates a sequence of k bracket pairs.)
There is no support for a rectangular multi-dimensional array creation method reference, most likely, because there is no actual use case that acted as a driving force. The one-dimensional array creation expression can be used together with Stream.toArray(…), allowing a more concise syntax than the equivalent lambda expression, despite there is no special support in the underlying architecture, i.e. int[]::new produces exactly the same compiled code as intArg -> new int[intArg]. There is no similar use case for a two (or even more) dimensional array creation, so there isn’t even a similar functional interface for a function consuming two or more int value and producing a reference type result.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With