在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

什么是函數式接口

科技綠洲 ? 來源:Java技術指北 ? 作者:Java技術指北 ? 2023-10-13 14:48 ? 次閱讀

Lambda表達式,相信大家都耳有所聞,而且不少小伙伴在日常的工作中也在使用。但說到函數式接口,可能有一些即使會使用Lambda表達式的小伙伴也會覺得陌生。今天,指北君就將帶領大家對Lambda、及其所使用的一些和函數式接口相關的知識點進行一個全面的學習。函數式接口所涉及的知識點包含:java.util.function包,@FunctoinInterface注解,Lambda表達式,雙冒號操作符。同時,我們還將對函數式接口的實現原理進行深入的剖析。

概述

函數式接口將分為三個篇章來為大家介紹:

  • (應用篇一)(1)函數式接口的來源,(2)Lambda表達式,(3)雙冒號運算符
  • (應用篇二)(4)詳細介紹@FunctionInterface注解(5)對java.util.function包進行解讀
  • (原理篇)介紹函數式接口的實現原理 應用篇將階段相關的JDK源碼以及給出典型的示例代碼 原理篇則從編譯、JVM維度來分析函數式接口的實現原理,具有一定深度,需要讀者具備一定的底層知識。

說明:源碼使用的版本為JDK-11.0.11

什么是函數式接口

【閱讀導引】:本節為概念性知識,純技術向伙伴可跳過

在分析具體內容之前,指北君帶領大家來對函數式接口做個基本的認知。函數式接口是JAVA語言為引入函數式編程而增加的特性,也即是說函數式接口式Java實現函數式編程的具體方式。那么,函數式編程到底是什么?他和面向對象編程又有什么關系?它能為我們帶來什么?我們又是否真的需要函數式編程?有很多小伙伴,可能和指北君一樣,是以面向對象語言開啟的編程世界的,對于函數式編程其實很陌生。所以,指北君在這里先給大家引薦編程界的三大流派(當然還有別的流派):過程式,函數式,對象式:

圖片
編程范式

函數式編程的思想脫胎于數學理論,也就是我們通常所說的λ演算(λ-calculus)。這也是為什么Java8中引入的函數式編程叫Lambda表達式的原因吧。如同數學中的函數一樣,函數式編程范式中的函數有獨特的特性,也就是通常說的無狀態或引用透明性。一個函數的輸出由且僅由其輸入決定,同樣的輸入永遠會產生同樣的輸出。

函數式編程的定義:"函數式編程是一種編程范式。它把計算當成是數學函數的求值,從而避免改變狀態和使用可變數據。它是一種聲明式的編程范式,通過表達式和聲明而不是語句來編程。" 函數式編程的代碼通常更加簡潔,但是不一定易懂。

近年來,隨著多核平臺和并發計算的發展,函數式編程的無狀態特性,在處理這些問題時有著其他編程范式不可比擬的天然優勢。這種發展也就進一步促使了Java引入函數式編程這一特性。

一個簡單示例

指北君先給大家展示一個簡單的函數式編程的示例:

/**
   * 簡單的函數式編程示例
   */
  public static void lambdaDemo1() {
    // 準備測試數據
    Integer[] data = new Integer[] {1, 2, 3};
    List< Integer > list = Arrays.asList(data);
    
    // 簡單示例:轉換單位并打印數據
    list.forEach(x - > System.out.println(String.format("Cents into Yuan: %.2f", x/100.0)));
  }

不熟悉Lambda表達式的小伙伴可能會好奇其中的語句:x -> System.out.println(String.format("Cents into Yuan: %.2f", x/100.0)),這是什么呢?這就是我們的Lambda表達式。通常,我們要訪問List對象,需要通過for、while等控制循環語句,并在循環中完成相關工作。有了函數式編程后,我們就可以使用Lambda表達式來完成對應的功能,是不是很簡潔!小伙伴們可能會奇怪,難道Lambda自動做了循環?當然不是,這里的循環控制并沒有減少,只是在forEach方法中而已。我們打開默認的迭代器forEach實現方法(ArrayList的forEach實現有差異,總體邏輯一致),代碼顯示forEach循環,并在循環中執行參數的函數邏輯。

default void forEach(Consumer< ? super T > action) {
        Objects.requireNonNull(action);
        for (T t : this) {
            action.accept(t);
        }
    }

既然沒有省略控制邏輯,難道我們費這么大的力氣引入這個東東就只是為了簡潔點?指北君畫了一下調用邏輯,參見下圖圖片

從上圖中大家是不是隱約可以看出:這種方式可以將控制部分和業務處理部分進行解耦,業務處理代碼更容易集中。

我們在分析forEach源碼的時候,看到forEach的參數類型為Consumer,打開Consumer源碼(主要接口聲明部分):

@FunctionalInterface
public interface Consumer< T > {
  ...
}

小伙伴們是不是發現這就是一個簡單的接口,接口使用了@FunctionInterface的接口,這是不是對Lambda表達式使用位置的約束呢?這個問題我們將在接下來的幾個章節給出答案。

Lambda表達式

在示例部分,指北君展示了在Java中如何Lambda進行函數式編程,小伙伴們是不是躍躍欲試想要動手了呢?在動手之前指北君先帶領大家了全面學習Lambda表達式的語法。下面給出幾種常見的Lambda代碼片段(代碼僅截取部分,無上下文):

() - > System.out.println("demo")
    ...
    list.forEach(x - >  System.out.print(x));
    ...
    map.forEach((x, y) - > {
      System.out.print(x);
      System.out.println(y);
    });
    ...
    (Integer x, String y) - > System.out.println("x: " + x ", y: " + y);

從上面代碼片段,可以看出Lambda表達式是通過->操作符來連接的,左邊為參數部分,右邊為表達式主體。

Lambda表達式語法:

  1. (parameters)->expression
  2. (parameters)->{statements;}

參數說明:([[type] parameter [, ...]])

  • 參數包括在圓括號內,參數數量可以0到多個,多個參數通過逗號“,”分割,例如(x, y)->
  • 參數類型可明確聲明,也可以省略,省略時根據上下文進行推斷, 例如:(x)->, (int x)->
  • 無參數,直接使用括號,例如:()->
  • 一個參數時,且參數類型省略,則括號可以省略 x->

表達式主體:

  • 由0到多條語句組成
  • 只有一條語句時,語句塊符號“{}”可省略,此時語句的結果將作為返回值,例如:->x*x, ->System.out.print(x)。
  • 超過一條語句時,必須使用語句塊符號“{}”包含起來。
  • 帶return關鍵字必須用代碼塊,例如:->{return x+x}。

常見的組合形式:

(int a, int b) - > {  return a + b; }

() - > System.out.println("Demo")

(String s) - > { 
  System.out.println(s); 
}

() - > 42

() - > { return 3.1415 };

啟動線程

new Thread(
    () - > System.out.println("start in thread.")
).start();

其他的代碼遵循基本的Java語法,小伙伴們現在就可以大展拳腳,試試通過Lambda表達式進行函數式編程。

雙冒號操作符

經過上一節的實踐,小伙伴們是不是很興奮了,可能有些小伙伴會問,Java類中的的方法也是函數,我可不可以在傳入Lambda表達式的地方傳入普通方法呢?類似下面這種效果:

List< String > list = new ArrayList< String >();
    ...
    list.forEach(xxxMethod());

想法是沒有問題的,但是形式錯誤了,首先xxxMethod()會直接觸發方法執行,并且返回的類型也不匹配forEach方法。那么,正確的形式應該如何寫呢?這就需要我們的雙冒號云算法登場了。雙冒號云算符標準名稱為eta-conversion,有下面四種常用場景

  1. 實例方法引用 object::instanceMethod
  2. 靜態方法引用 Class::staticMethod
  3. 實例方法引用(實例作為參數傳入) Class::instanceMethod
  4. 構造方法引用 Class:new
  • 無參數:Supplier
  • 一個參數:Function
  • 二個參數:BiFunction
  • 更多:自定義函數接口

示例代碼

public class FunctionInterfaceInvoke {

  public static void main(String[] args) {
    
    // 1-1 構造方法(無參數),編譯會做參數檢查(包含輸入參數和返回值)
    Supplier< FunctionInterfaceInvoke > s = FunctionInterfaceInvoke::new;
    s.get();
    
    //1-2 構造方法(1個參數)
    IntFunction< FunctionInterfaceInvoke > func = FunctionInterfaceInvoke::new;
    func.apply(1);
    
    // 1-3 構造方法(多個參數)
    BiFunction< Integer, Integer, FunctionInterfaceInvoke > func2 = FunctionInterfaceInvoke::new;
    func2.apply(1, 2);
    
    // 2 靜態方法
    Consumer< Integer > sta1 = FunctionInterfaceInvoke::staticMethod;
    sta1.accept(1);
    
    // 3 實例方法
    IntConsumer sta2 = new FunctionInterfaceInvoke()::instanceMethod;
    sta2.accept(2);

  }

  public FunctionInterfaceInvoke() {
    System.out.println("none parameters");
  }
  
  public FunctionInterfaceInvoke(int p1) {
    System.out.println("constructor whith one parameter: " + p1);
  }
  
  public FunctionInterfaceInvoke(Integer p1, Integer p2) {
    System.out.println(String.format("constructor whith 2 parameters %1s, %2s", p1, p2));
  } 
  
  public static void staticMethod(Integer p1) {
    System.out.println("static method:" + p1);
  }
  
  public void instanceMethod(int p1) {
    System.out.println("instance method:"+p1);
  }
}

小結

函數式接口應用篇的第一部分就給大家介紹到這里,本篇我們介紹了什么是函數式編程,一個簡單示例,Lambda表達式詳細說明和雙冒號操作的使用。下一篇我們將會繼續介紹函數式接口的應用,學習 @FunctionInterface注解和java.util.function包中的接口。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 接口
    +關注

    關注

    33

    文章

    8885

    瀏覽量

    152960
  • 源碼
    +關注

    關注

    8

    文章

    665

    瀏覽量

    30050
  • 函數
    +關注

    關注

    3

    文章

    4365

    瀏覽量

    63840
  • Lambda
    +關注

    關注

    0

    文章

    30

    瀏覽量

    10056
收藏 人收藏

    評論

    相關推薦

    Java基礎教程Java入門到精通day23_06_常用函數接口之Consumer

    JAVA
    電子學習
    發布于 :2023年01月13日 11:25:07

    Java基礎教程Java入門到精通day23_08_常用函數接口之Predicate

    JAVA
    電子學習
    發布于 :2023年01月13日 11:40:10

    Java基礎教程Java入門到精通day23_09_常用函數接口之Predicate

    JAVA
    電子學習
    發布于 :2023年01月13日 11:42:42

    Java基礎教程Java入門到精通day23_02_函數接口作為方法的參數

    JAVA
    電子學習
    發布于 :2023年01月13日 11:56:39

    Java基礎教程Java入門到精通day23_01_函數接口

    JAVA
    電子學習
    發布于 :2023年01月13日 11:58:28

    Java基礎教程Java入門到精通day23_11_常用函數接口之Function

    JAVA
    電子學習
    發布于 :2023年01月13日 12:17:04

    Java 8 Stream流底層原理

    初識lambda呢,函數接口肯定是繞不過去的,函數接口就是一個有且僅有一個抽象方法,但是可以
    的頭像 發表于 11-18 10:27 ?1522次閱讀

    基于JDK 1.8來分析Thread類的源碼

    由上圖我們可以看出,Thread類實現了Runnable接口,而Runnable在JDK 1.8中被@FunctionalInterface注解標記為函數接口,Runnable
    的頭像 發表于 02-06 17:12 ?841次閱讀

    如何使用lambda表達式提升開發效率?

    Java8 的一個大亮點是引入 Lambda 表達式,使用它設計的代碼會更加簡潔。當開發者在編寫 Lambda 表達式時,也會隨之被編譯成一個函數接口
    發表于 08-24 10:25 ?384次閱讀

    Map+函數接口如何完美的解決if-else問題?

    最近寫了一個服務:根據優惠券的類型resourceType和編碼resourceId來 查詢 發放方式grantType和領取規則
    的頭像 發表于 09-07 11:07 ?631次閱讀
    Map+<b class='flag-5'>函數</b><b class='flag-5'>式</b><b class='flag-5'>接口</b>如何完美的解決if-else問題?

    JDK中常見的Lamada表達式

    JDK中有許多函數接口,也會有許多方法會使用函數接口作為參數,同時在各種源碼中也大量使用了這
    的頭像 發表于 10-10 15:07 ?713次閱讀
    JDK中常見的Lamada表達式

    動態函數接口的調用原理

    本篇將從編譯,執行層面為大家講解函數接口運行的機制,讓各位小伙伴更進一步加深對函數接口的理解
    的頭像 發表于 10-13 11:27 ?607次閱讀
    動態<b class='flag-5'>函數</b><b class='flag-5'>接口</b>的調用原理

    函數接口的應用知識點

    概述 函數接口將分為三個篇章來為大家介紹: (應用篇一)(1)函數接口的來源,(2)Lamb
    的頭像 發表于 10-13 11:32 ?820次閱讀
    <b class='flag-5'>函數</b><b class='flag-5'>式</b><b class='flag-5'>接口</b>的應用知識點

    妙用Java 8中的 Function接口,消滅if...else(非常新穎的寫法)

    使用注解@FunctionalInterface標識,并且只包含一個抽象方法的接口函數接口函數
    的頭像 發表于 11-10 16:23 ?1171次閱讀
    妙用Java 8中的 Function<b class='flag-5'>接口</b>,消滅if...else(非常新穎的寫法)

    Java 枚舉與策略模式、函數接口的結合:實現高內聚低耦合的設計

    中,通常會使用枚舉來定義業務上的一組常量,那除了簡單地定義常量之外,我們如何利用枚舉來實現高內聚、低耦合的設計呢?下面介紹下枚舉和策略模式、函數接口的組合應用。 二、枚舉+策略模式 首先介紹下策略模式,已經掌握策略模式的同學可
    的頭像 發表于 11-21 14:06 ?491次閱讀
    主站蜘蛛池模板: 亚洲欧美日韩另类精品一区二区三区 | 成人亚洲综合 | 综合欧美一区二区三区 | 免费观看高清视频 | 俺也操| 欧美精品一区视频 | 99国产精品农村一级毛片 | 久久午夜宅男免费网站 | 婷婷色九月 | 国产精品天天影视久久综合网 | 5566成人 | 1024手机看片欧美日韩 | 男男浪荡双性受hplay | 日本xxxx色视频在线观看免费 | 国产香蕉一区二区精品视频 | 免费国产一区 | bt种子在线www天堂官网 | 黄网在线免费观看 | 婷婷久久久五月综合色 | 婷婷六月丁香 | 国产女人水多白浆 | 六月婷操 | 又粗又硬又爽又黄毛片 | 亚洲大胆精品337p色 | 欧美亚洲一区二区三区在线 | 免费观看一级特黄三大片视频 | 丝袜美腿一区 | 欧美啪啪小视频 | 国产亚洲一区二区三区啪 | 五月天停婷基地 | 天天亚洲 | 午夜男人影院 | 久碰香蕉精品视频在线观看 | 亚洲欧洲色天使日韩精品 | 欧美午夜性刺激在线观看免费 | 亚洲成a人片在线观看88 | 黄网站在线观看高清免费 | 国产精品99r8在线观看 | 国产自在自线午夜精品视频 | 开心丁香婷婷深爱五月 | 77se77亚洲欧美在线大屁股 |