Mục lục
Functional Interface là một interface chứa duy nhất một abstract method. Từ java 8 trở đi lambda expressions được sử dụng nhiều với functional interface để thể hiện một implement của nó.
Một functional interface có thể có nhiều default method nên các bạn đừng nhầm tưởng rằng functional interface lại có nhiều method thế kia nhé, nó chỉ có một abstract method duy nhất thôi!
Ví dụ chúng ta có Runnable interface là một functional interface
@FunctionalInterface public interface Runnable { /** * When an object implementing interface <code>Runnable</code> is used * to create a thread, starting the thread causes the object's * <code>run</code> method to be called in that separately executing * thread. * <p> * The general contract of the method <code>run</code> is that it may * take any action whatsoever. * * @see java.lang.Thread#run() */ public abstract void run(); }
Annotation @FunctionalInterface đặt ở đầu interface cho chúng ta dễ dàng nhận biết nó là một functional interface. Điều quan trọng là annotation @FunctionalInterface sẽ đảm bảo cho interface của chúng ta chỉ có duy nhất một abstract method. Nếu chúng ta khai báo nhiều hơn một abstract method trong interface được đánh dấu @FunctionalInterface thì chúng ta sẽ nhận được lỗi ‘Unexpected @FunctionalInterface annotation’.
Thực hành với functional interface
Implement Runnable functional interface bằng Anonymous class.
public class Main { public static void main(String args[]) { // create anonymous inner class object new Thread(new Runnable() { @Override public void run() { System.out.println("New thread created"); } }).start(); } }
OutputNew thread created
Functional interface với lambda expressions. Từ java 8 trở đi thì cặp đôi này luôn đi liền với nhau nên các bạn cố gắng hiểu xíu về lambda expression.
public class Main { public static void main(String args[]) { // create anonymous inner class object new Thread(() -> System.out.println("New thread created")).start(); } }
Output New thread created
Tự xây dựng một functional interface
Mỗi một functional interface đều có một ý nghĩa rõ ràng mà khi chúng ta nhắc về nó thì sẽ biết ngay những thằng implement từ đó chắc chắn sẽ làm nhiệm vụ gì. Ví dụ như Comparator thì mô tả kết quả so sánh giữa 2 object, Predicate dùng để kiểm tra tính đúng sai của mệnh đề điều kiện etc.
Giờ mình sẽ xây dựng một Square Functional interface có chứa duy nhất một calculate() abstract method
@FunctionalInterface interface Square { int calculate(int x); } class Main { public static void main(String args[]) { /** * Square: functional interface * (int x)->x*x: la phan implement cua s theo dang anonymous class * => s la mot instance cua anonumous class implement Square */ Square s = (int x)->x*x; int ans = s.calculate(10); System.out.println(ans); } }
Output:100
Một số functional interface dựng sẵn
Trong java.util.function package chứa một số functional interface được dựng sẵn:
Predicate: Predicate áp dụng cho các trường hợp kiểm tra một điều kiện cụ thể.
@FunctionalInterface public interface Predicate<T> { /** * Evaluates this predicate on the given argument. * * @param t the input argument * @return {@code true} if the input argument matches the predicate, * otherwise {@code false} */ boolean test(T t); // ... }
BiFunction: Nhận 2 tham số x, y và trả về kết quả sau quá trình tính toán dự trên x, y.
@FunctionalInterface public interface BiFunction<T, U, R> { /** * Applies this function to the given arguments. * * @param t the first function argument * @param u the second function argument * @return the function result */ R apply(T t, U u); // .... }
Function: Nhận một tham số x và trả về kết quả dựa trên quá trình tính toàn từ x.
@FunctionalInterface public interface Function<T, R> { /** * Applies this function to the given argument. * * @param t the function argument * @return the function result */ R apply(T t); // ... }
Ví dụ sử dụng Predicate function interface để kiểm tra một ArrayList String và in ra các chuỗi bắt đầu bằng chữ “H”
import java.util.Arrays; import java.util.List; import java.util.function.Predicate; class Main { public static void main(String args[]) { // create a list of strings List<String> names = Arrays.asList("HGA", "FAS", "HGI", "GET"); Predicate<String> p = (s)->s.startsWith("H"); // Iterate through the list for (String st:names) { // call the test method if (p.test(st)) System.out.println(st); } } }
Output
HGA
HGI