menu

VanThuong.Com

Blog học lập trình Java và SEO miễn phí.

Java 8 - Tìm hiểu Functional Interfaces trong 5 phút

Posted by on
Khi lập trình trên ngôn ngữ Java, tôi dám cá rằng bạn đã ít nhất một lần sử dụng các interface sau cho công việc của mình: java.lang.Runnable, java.awt.event.ActionListener, java.util.Comparator, java.util.concurrent.Callable. Đây là những interface phổ biến nhất mà chúng ta thường sử dụng và nó chỉ có một phương thức duy nhất được khai báo. Java 8 cung cấp cho chúng ta khá nhiều Functional Interfaces và trong bài viết về Lambda Expression tôi đã có đề cập đến. Chúng ta sẽ cùng tìm hiểu kỹ hơn khái niệm Functional Interface trong bài viết này.
Java 8 - Tìm hiểu Functional Interfaces trong 5 phút

Functional Interfaces là gì?

Như ở trên tôi có liệt kê một số interface phổ biến mà chúng ta thường sử dụng. Đặc điểm của nó là chỉ chứa một phương thức abstract duy nhất mà những class nào implements từ nó phải Override lại. Các interface này được gọi là Single Abstract Method interfaces (SAM Interfaces). Một cách sử dụng phổ biến mà chúng ta thường dùng đó là viết lại với Anonymous Inner class.

Ví dụ
public class AnonymousInnerClassTest {
  public static void main(String[] args) {
    new Thread(new Runnable() {
      @Override
      public void run() {
        System.out.println("Display some text");
      }
    }).start();
  }
}
Trong Java 8, khái niệm về SAM Interfaces đã được thay đổi và chúng ta gọi nó là Functional Interfaces. Các interface này có thể được sử dụng bởi Lambda Expressions, Method References và Constructor References.

Java 8 cũng giới thiệu một annotation mới là @FunctionalInterface. Nó có thể sử dụng cho mục đích bắt lỗi ở thời điểm biên dịch nếu như interface mà bạn đã chú thích bằng annotation này vi phạm quy tắc của Functional Interface.

Dưới đây là một ví dụ minh họa về Functional Interface để bạn làm quen với nó
@FunctionalInterface
public interface DemoFunctionalInterface {
  void doFirstWork();
}
Từ ví dụ minh họa trên, nếu như bạn thêm vào một phương thức abstract khác cho interface này như sau
@FunctionalInterface
public interface DemoFunctionalInterface {
  void doFirstWork();

  void doSecondWork();
}
Thì khi biên dịch bạn sẽ nhận được thông báo lỗi vì đã vi phạm quy tắc của Functional Interface
Lỗi biên dịch Functional Interface
Danh sách Functional Interfaces có sẵn trong Java 8 → Nhấp để xem

Để làm việc hiệu quả với Functional Interface

Bên dưới đây là danh sách những điều mà bạn nên ghi nhớ khi làm việc với Functional Interface.

1) Như đã đề cập ở trên, một functional interface chỉ chứa duy nhất một phương thức abstract. Phương thức abstract thứ 2 sẽ phá vỡ quy tắc của functional interface. Nếu như chúng ta loại bỏ @FunctionalInterface annotation, chúng ta có thể thêm vào các phương thức abstract khác, nhưng lúc này nó không còn là functional interface nữa.

2) Functional Interface vẫn được coi là hợp lệ nếu chúng ta bỏ đi khai báo @FunctionalInterface và nó chỉ chứa một phương thức abstract duy nhất. Annotation này chỉ nhấn mạnh cho compiler biết rằng chỉ được phép có duy nhất 1 phương thức abstract trong interface.

3) Về mặt khái niệm, môt functional interface chỉ chứa duy nhất một phương thức abstract. Nhưng chúng ta có thể thêm vào các default method mà không làm phá vỡ quy tắc này bởi chúng không phải là phương thức abstract. Tôi sẽ giới thiệu rõ hơn về default method trong bài viết khác. Dưới đây là một ví dụ về Functional Interface hợp lệ với các default method.
@FunctionalInterface
public interface DemoFunctionalInterface {
  void doFirstWork();

  default void doSecondWork() {
    // Method body
  }

  default void doThirdWork() {
    // Method body
  }
}

4) Một interface có thể extends từ một interface khác. Nếu như interface B được extends từ một functional interface khác thì B vẫn được gọi là Functional Interface nếu và chỉ nếu nó không thêm vào bất kỳ một phương thức abstract nào khác. Interface B có thể thêm vào các default method hoặc override lại các phương thức của java.lang.Object.

@FunctionalInterface
public interface DemoFunctionalInterface {
  void doFirstWork();

  default void doSecondWork() {
    // Method body
  }

  @Override
  String toString();

  @Override
  boolean equals(Object obj);
}

Như vậy là chúng ta vừa tìm hiểu xong một khái niệm mới trong Java 8. Trong khuôn khổ bài viết này thì tôi chỉ chia sẻ đến đây thôi. Hi vọng trong các bài viết khác tôi sẽ giới thiệu đến các bạn nhiều hơn về các Functional Interface và các sử dụng nó như thế nào. Hiện tại thì trong bài viết về Lambda Expression tôi đã có sử dụng một vài Functional Interface như: Function, Predicate, Consumer rồi đấy các bạn có thể xem lại nhé. Chúc các bạn học tốt.
Thương Nguyễn
Đăng bình luận

menu