1. Các phương thức hàm

Nếu một giao diện chỉ có một phương thức , thì một biến của loại giao diện đó có thể được gán một giá trị do biểu thức lambda (hàm lambda) đưa ra. Các giao diện như vậy được gọi là giao diện chức năng (sau khi Java thêm hỗ trợ cho các hàm lambda).

Ví dụ, Java có giao Consumer<Type>diện, có phương accept(Type obj)thức. Tại sao giao diện này là cần thiết?

Trong Java 8, các bộ sưu tập có một forEach()phương thức cho phép bạn thực hiện một số hành động cho từng phần tử của bộ sưu tập . Và ở đây, Consumer<T>giao diện chức năng được sử dụng để truyền hành động cho forEach()phương thức.

Đây là cách bạn có thể hiển thị tất cả các phần tử của một bộ sưu tập :

ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "Hello", "how's", "life?");

list.forEach( (s) -> System.out.println(s) );
Hiển thị tất cả các thành phần của bộ sưu tập (sử dụng biểu thức lambda)

Trình biên dịch sẽ chuyển đổi mã ở trên thành mã bên dưới:

ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "Hello", "how's", "life?");

list.forEach(new Consumer<String>()
{
   public void accept(String s)
   {
      System.out.println(s));
   }
});
Hiển thị tất cả các thành phần của bộ sưu tập (sử dụng lớp ẩn danh)

Phiên bản đầu tiên chắc chắn ngắn hơn phiên bản thứ hai. Và trong khi mã có biểu thức lambda khó đọc, thì mã có lớp bên trong ẩn danh đôi khi còn khó đọc hơn.



2. Phương pháp tham khảo

Tuy nhiên, mã biểu thức lambda của chúng tôi có thể được viết ngắn hơn nữa.

Đầu tiên, bạn có thể bỏ qua dấu ngoặc đơn xung quanh stham số:

list.forEach( (s) -> System.out.println(s) );
Trước
list.forEach( s -> System.out.println(s) );
Sau đó

Điều này chỉ có thể được thực hiện nếu có một tham số . Nếu có nhiều tham số thì phải dùng dấu ngoặc đơn .

Và thứ hai, bạn có thể viết nó như thế này:

list.forEach( System.out::println );
Ký hiệu nhỏ gọn nhất

Đây là ký hiệu chính xác tương tự. Lưu ý rằng không có dấu ngoặc đơn sau phần mở rộng println.

Ở đây chúng ta có cùng mã - một cuộc gọi phương thức:

object::method
x -> object.method(x)

Hãy suy nghĩ về nó: chúng tôi muốn thực hiện một số hành động cho từng thành phần của bộ listsưu tập. Nếu hành động là một lệnh gọi hàm duy nhất (chẳng hạn như println()), thì bạn chỉ cần truyền hàm cho phương thức dưới dạng tham số là hợp lý.

Nhưng làm thế nào để chúng ta giải thích với trình biên dịch rằng chúng ta muốn truyền phương thức hơn là gọi nó? Để làm điều này, thay vì toán tử dấu chấm, chúng ta sử dụng hai dấu hai chấm trước tên phương thức. Một dấu hai chấm đã được sử dụng để biểu thị toán tử bậc ba.

Đây là ký hiệu đơn giản và nhỏ gọn nhất.



3. Trình tạo

Các tham chiếu phương thức với hai dấu hai chấm rất thuận tiện khi chúng ta làm việc với các luồng I/O. Bạn sẽ thấy điều này một lát sau.

Trong khi chờ đợi, hãy nói về 3 cách phổ biến để truyền một tham chiếu phương thức:

Tham chiếu đến một phương thức của một đối tượng

Để chuyển một tham chiếu đến một phương thức của một đối tượng, bạn cần viết một cái gì đó như . Mã này tương đương với .object::method
x -> object.method(x)

Các biến đặc biệt thissupercó thể được sử dụng làm đối tượng.

Tham chiếu đến một phương thức của một lớp

Để chuyển một tham chiếu đến một phương thức tĩnh, bạn cần viết một cái gì đó như . Mã này được chuyển đổi thành mã nhưclass::methodx -> class.method(x);

Tham chiếu đến một hàm tạo

Một hàm tạo hoạt động tương tự như một phương thức lớp tĩnh, vì vậy bạn cũng có thể chuyển một tham chiếu đến một hàm tạo. Đây là giao diện của nó: .class::new

Ví dụ: bạn có thể thực hiện xung quanh việc xóa kiểu cho các bộ sưu tập và chuyển phương toArray()thức tham chiếu đến một hàm tạo sẽ tạo mảng mong muốn:toArray(int[]::new);