java程式碼之美(14)---Java8 函式式介面
阿新 • • 發佈:2020-02-11
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() { } }
2) 錯誤示例
加上@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)