2016-11-12 30 views
7

Trong Java chúng tôi có thể tạo IntFunction<String[]> từ 1D constructor mảng tham khảo:Phương pháp tham chiếu đến các mảng đa chiều trong Java 8

// both do the same thing 
    IntFunction<String[]> createArrayL = size -> new String[size]; 
    IntFunction<String[]> createArrayMR = String[]::new; 

Bây giờ tôi tự hỏi tại sao chúng ta không thể làm điều này với một mảng 2D:

BiFunction<Integer, Integer, String[][]> createArray2DL = 
      (rows, cols) -> new String[rows][cols]; 

    // error: 
    BiFunction<Integer, Integer, String[][]> createArray2DMR = 
      String[][]::new; 

Tất nhiên chúng tôi có thể viết:

IntFunction<String[][]> createArray2DInvalidL = String[][]::new; 
    System.out.println(createArray2DInvalidL.apply(3)[0]); // prints null 

nhưng điều này sẽ hoạt động khác với:

new String[3][3] 

vì mảng hàng sẽ không được khởi tạo.

Vì vậy, câu hỏi của tôi là: tại sao String[][]::new không hoạt động đối với mảng 2D (đối với tôi có vẻ như sự không nhất quán trong thiết kế ngôn ngữ)?

Trả lời

8

Thực sự là một trường hợp thú vị.

Vấn đề là String[][]::new là hàm có số nguyên là 1 (là hàm tạo của mảng mảng) và không thể coi là hàm sinh (số 2) và ví dụ new String[3][3] có hai tham số thay vì một.

Trong trường hợp này, createArray2DInvalidL.apply(3) bằng gọi new String[3][];

Những gì bạn có thể tìm kiếm là:

IntFunction<String[][]> createArray2D = n -> new String[n][n];

Kích thước không cần phải có độ dài bằng nhau và có vẻ như một giả định khá hợp lý.

http://4comprehension.com/multidimensional-arrays-vs-method-references/

+2

và tại sao 'BiFunction createArray2DL = (a, b) -> String [] [] :: new;' tạo ra lỗi ?? – user43968

+0

@ user43968 vì trong biểu thức lambda của bạn, bạn đang trả về hàm khác '' 'BiFunction > createArray2DL = (a, b) -> String [] [] :: new;' '' –

1

Không có mâu thuẫn ở đây. Nếu bạn viết một tuyên bố như

IntFunction<ElementType[]> f = ElementType[]::new; 

bạn tạo một hàm mà đánh giá sẽ trả về một mảng mới với mỗi mục là khả năng nắm giữ một tài liệu tham khảo của ElementType, khởi tạo null. Điều này không thay đổi, khi bạn sử dụng String[] cho ElementType.

Nhưng nó cũng đã được giải quyết một cách rõ ràng trong The Java Language Specification, §15.13.3. Run-Time Evaluation of Method References:

Nếu hình thức là Loại [] k :: mới (k ≥ 1), sau đó cơ thể của phương pháp gọi có cùng tác dụng như biểu thức tạo mảng của biểu mẫu mới Nhập [size] [] k-1, trong đó kích thước là tham số đơn của phương thức gọi. (Ký hiệu [] k cho biết một chuỗi gồm k cặp ngoặc vuông.)

Không có hỗ trợ cho tham chiếu phương thức tạo mảng đa chiều hình chữ nhật, rất có thể, vì không có trường hợp sử dụng thực tế hoạt động như động lực. Biểu thức tạo mảng một chiều có thể được sử dụng cùng với Stream.toArray(…), cho phép cú pháp ngắn gọn hơn biểu thức lambda tương đương, mặc dù không có hỗ trợ đặc biệt trong kiến ​​trúc cơ bản, tức là int[]::new tạo chính xác mã được biên dịch giống như intArg -> new int[intArg]. Không có trường hợp sử dụng tương tự cho việc tạo mảng hai (hoặc thậm chí nhiều hơn), do đó, thậm chí không có giao diện chức năng tương tự cho hàm sử dụng hai hoặc nhiều giá trị int và tạo kết quả kiểu tham chiếu.

+0

My điểm là vì trong Java bạn có thể tạo mảng 2d bằng 'new Element [5] [6]' hoặc bằng 'new Element [5] []' (tất nhiên trong trình biên dịch case đầu tiên cũng sẽ phân bổ các hàng cho tôi) sau đó Java nên cho phép cùng với tham chiếu hàm tạo. Tôi bối rối vì nếu trình biên dịch có thể phân bổ các hàng trong biểu thức 'mới X [a] [b]' thì tại sao không trong 'X [] [] :: new' - sự kiện nếu điều đó có nghĩa là tạo ra biểu thức lambda tổng hợp. – csharpfolk

+0

Không ai nói rằng sẽ không thể viết trình biên dịch có khả năng tạo ra mã như vậy. Nhưng các nhà thiết kế ngôn ngữ không thêm cú pháp cho nó. Cú pháp cho tham chiếu phương thức tạo mảng một chiều hoạt động nhất quán, ngay cả khi loại phần tử là một mảng chính nó. Cú pháp tham chiếu phương thức tạo mảng đa chiều hình chữ nhật giả thiết phải khác với cú pháp, vì nó sẽ không được chấp nhận nếu 'X [] [] :: new' đôi khi tạo ra các mảng con và đôi khi không. Sẽ không có nhiều lợi thế của cú pháp bổ sung so với một biểu thức lambda tương đương. – Holger

Các vấn đề liên quan