Java8新特性—四大內置函數式接口

Java8新特性——四大內置函數式接口預備知識背景Lambda 的設計者們為了讓現有的功能與 Lambda 表達式良好兼容,考慮了很多方法,于是產生了函數接口這個概念 。
什么是函數式接口?函數式接口指的是一個有且僅有一個抽象方法,但是可以有多個非抽象方法的接口,這樣的接口可以隱式轉換為 Lambda 表達式 。
但是在實踐中,函數式接口非常脆弱,只要某個開發者在該接口中添加一個函數 , 則該接口就不再是函數式接口進而導致編譯失敗 。為了克服這種代碼層面的脆弱性,并顯式說明某個接口是函數式接口,Java 8 提供了一個特殊的注解@FunctionalInterface,舉個簡單的函數式接口的定義:
@FunctionalInterface public interface GreetingService {     void sayMessage(String message); } Java7 只能通過匿名內部類進行編程,例如:
GreetingService greetService = new GreetingService() {      @Override     public void sayMessage(String message) {         System.out.println("Hello " + message);     } }; greetService.sayMessage("world"); Java8 可以采用 Lambda 表達方進行編程,例如:
GreetingService greetService = message -> System.out.println("Hello " + message); greetService.sayMessage("world"); 目前 Java 庫中的所有相關接口都已經帶有這個注解了,實踐上java.lang.Runnable和java.util.concurrent.Callable是函數式接口的最佳例子!
@FunctionalInterface注解Java 8為函數式接口引入了一個新注解@FunctionalInterface,主要用于編譯級錯誤檢查,加上該注解,當你寫的接口不符合函數式接口定義的時候,編譯器會報錯 。
正確例子 , 沒有報錯:
/** * @Description FunctionalInterface * @Author vchicken * @Date 2022/9/24 14:46 */@FunctionalInterfacepublic interface TestFunctionalInterface {void sayMessage(String message);}錯誤例子,接口中包含了兩個抽象方法,違反了函數式接口的定義,Eclipse報錯提示其不是函數式接口 。

Java8新特性—四大內置函數式接口

文章插圖
提醒:加不加@FunctionalInterface對于接口是不是函數式接口沒有影響,該注解知識提醒編譯器去檢查該接口是否僅包含一個抽象方法 。
四大函數式接口1.Function接口什么是Function接口?
Java8新特性—四大內置函數式接口

文章插圖
從Function接口的源代碼,我們可以看出,JDK1.8之后才加入這個接口 。Functional接口類中只有一個抽象方法待實現,符合函數式接口(指的是一個有且僅有一個抽象方法,但是可以有多個非抽象方法的接口) , 因此Function接口可以用Lambda表達式——這個方法就是apply 。
從源碼可以看出 , 入參和出參類型,用泛型動態指定 。apply的具體邏輯就相當于是入參轉化為出參的具體邏輯 。也就相當于是y = f(x)這個里面的,映射法則f 。具體邏輯需要我們用匿名內部類或者Lambda,寫方法體來實現 。因此這個接口又叫函數型接口 。
下面我們來用代碼舉栗如何使用Function接口:
public class FunctionTest {public static void main(String[] args) {// 如果入參為null,則回參為0 , 否則返回入參的值作為出參Function<Integer, Integer> function1 = s -> s == null ? 0 : s;// 將入參的值+1后作為回參返回Function<Integer, Integer> function2 = s -> s + 1;// 如果入參為null,則回參為"",否則返回入參的值作為出參Function<String, String> function3 = s -> s == null ? "空的" : s;System.out.println(function1.apply(null));System.out.println(function1.apply(100));System.out.println(function2.apply(10));System.out.println(function3.apply(null));System.out.println(function3.apply("hello world!"));// andThen是先執行前面的操作,然后執行andThen之后的操作Function<Integer, Integer> first = x -> x * x;Function<Integer, Integer> after = y -> y * 2;System.out.println(first.apply(3));System.out.println(after.apply(3));int res = first.andThen(after).apply(4);System.out.println(res);}}執行結果
010011空的hello world!9632從上面的栗子我們可以看出:
Java把這些映射規則,也就是y = f(x)中的【f】抽象成了這個Function接口的apply邏輯 。然后x和y,自變量和因變量,也就是入參出參,Java使用了擴展性更強的泛型參數類型,而不是固定Object入參出參 。因為固定Object的話還要涉及到類型轉換,還有可能報ClassCast異常,很麻煩

推薦閱讀