java代碼之美(14)---Java8 函數式接口


Java8 函數式接口

之前寫了有關JDK8的Lambda表達式:java代碼之美(1)---Java8 Lambda

函數式接口可以理解就是為Lambda服務的,它們組合在一起可以讓你的代碼看去更加簡潔。

一、概念

1、什么是函數式接口

概念 所謂的函數式接口, 當然首先是一個接口, 然后就是在這個接口里面 只能有一個抽象方法

有關函數式接口,有個專門的注解叫:@FunctionalInterface。該注解主要特點有:

1、該注解只能標記在"有且僅有一個抽象方法"的接口上,表示函數式接口。
2、JDK8接口中的靜態方法和默認方法,都不算是抽象方法。
3、接口默認繼承 java.lang.Object,所以如果接口顯示聲明覆蓋了Object中的方法,那么也不算抽象方法。
4、允許java.lang.Object中的public方法
5、該注解不是必須的,如果一個接口符合"函數式編程"定義,那么加不加該注解都沒有影響。加上該注解能夠 更好地讓編譯器進行檢查,
如果編寫的不是函數式接口,但是加上了@FunctionalInterface 那么編譯器會報錯。

2、示例

  1. 正確示例
/**
 * 函數式接口注解
 */
@FunctionalInterface
public interface PersonInterface { 
    /**
     * 1、僅有一個抽象方法
     */
     void say();
     
    /**
     * 2、java.lang.Object中的方法不算
     */
    @Override
     boolean equals(Object var1);
    
    /**
     * 3、java8 接口才可以有默認的方法實現 前提是方法名稱必須使用default關鍵字修飾
     */
     default void defaultMethod() {
        System.out.println("haha");
    }
    
    /**
     * 4、靜態方法
     */
     static void staticMethod() {
    }
}
  1. 錯誤示例

加上@FunctionInterface,就代表該接口是函數式接口,只能有一個抽象方法,如果有多個編譯時就會直接報錯。

3、為什么只能有一個抽象方法

其實這個問題很好去理解,上面說了函數式接口主要是為Lambda語法服務的,為了讓代碼看去更加簡潔。

下面通過示例來說明

     public static void main(String[] args) {
       //上面的接口 通過Lambda表達式重新 say方法 
        PersonInterface inter = () -> System.out.println("我說什么好呢?");
        inter.say();
        //控制台輸出: 我說什么好呢?
    }

通過 函數式接口 + Lambda表達式 讓代碼看去變的簡潔,而這里的關鍵點在於:

 ()->{} 就是代表對say()方法的重寫

如果你有個多個抽象方法, 那么()-> {} 這種寫法,編譯器就不知道這是重寫的哪個方法了。所以這就是為什么只能有一個抽象方法的原因。


二、綜合示例

這里再舉一個綜合示例,來方便理解它們。

自定義函數式接口

/**
  * 自定義函數TestFunction,提供handler接口, 傳入的是A,返回的是B
  */
@FunctionalInterface
public interface MyFunction<A, B> {

    /**
      * @Description: 傳入的是A 返回的是B
      */
    B handler(A a, A a1);
}

Student對象

public class Student {
    /**
     * 姓名
     */
    private String name;
    /**
     * 年齡
     */
    private Integer age;
    
    //省略 set get toString 全參數構造函數 無參構造函數
  }

測試類

   public static void main(String[] args) {
        //1、求和 傳入Integer返回Integer類型
        MyFunction<Integer, Integer> myFunction1 = (x, y) -> {
            //返回總和
            return x + y;
        };
        Integer count = myFunction1.handler(5, 10);
        System.out.println("輸出總和為:" + count);


        //2、求和 傳入Integer返回String類型
        MyFunction<Integer, String> myFunction2 = (x, y) -> {
            //返回總和
            return x + " + " + y + " = " + (x + y);
        };
        System.out.println(myFunction2.handler(5, 10));


        //3、對象處理 過濾對象
        List<Student> students = Arrays.asList(new Student("小明", 3), new Student("小白", 13), new Student("小黃", 18));
        MyFunction<Integer, List<Student>> myFunction3 = (x, y) -> {
            //這里通過java8 的stream來過濾 年齡大於x 且小於y的對象
            List<Student> studentList = students.stream().filter(student -> student.getAge() > x && student.getAge() < y).collect(Collectors.toList());
            return studentList;
        };

        List<Student> list = myFunction3.handler(5, 15);
        //遍歷集合 輸出對象
        list.forEach(x -> System.out.println(x));
    }

運行結果

從運行結果可以很明顯看出,集合對象經過過濾只剩下一個滿足條件的了。



你如果願意有所作為,就必須有始有終。(24)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM