欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java8中的lambda表達(dá)式簡(jiǎn)介

 更新時(shí)間:2022年06月26日 09:20:11   作者:morris131  
Lambda表達(dá)式類似匿名函數(shù),簡(jiǎn)單地說(shuō),它是沒有聲明的方法,也即沒有訪問(wèn)修飾符、返回值聲明和方法名,這篇文章主要介紹了java8?中的lambda表達(dá)式簡(jiǎn)介,需要的朋友可以參考下

Lambda表達(dá)式類似匿名函數(shù),簡(jiǎn)單地說(shuō),它是沒有聲明的方法,也即沒有訪問(wèn)修飾符、返回值聲明和方法名。

Lambda允許把函數(shù)作為一個(gè)方法的參數(shù)(函數(shù)作為參數(shù)傳遞進(jìn)方法中)。

Lambda表達(dá)式的語(yǔ)法

(parameters) -> expression
或
(parameters) -> { statements; }

參數(shù)說(shuō)明:

  • 可選類型聲明:不需要聲明參數(shù)類型,編譯器可以統(tǒng)一識(shí)別參數(shù)值。
  • 可選的參數(shù)圓括號(hào):一個(gè)參數(shù)無(wú)需定義圓括號(hào),但多個(gè)參數(shù)需要定義圓括號(hào)。
  • 可選的大括號(hào):如果主體包含了一個(gè)語(yǔ)句,就不需要使用大括號(hào)。
  • 可選的返回關(guān)鍵字:如果主體只有一個(gè)表達(dá)式返回值則編譯器會(huì)自動(dòng)返回值,大括號(hào)需要指明表達(dá)式返回了一個(gè)數(shù)值。

舉例說(shuō)明:

// 1. 不需要參數(shù),返回值為5
() -> 5

// 2. 接收一個(gè)參數(shù)(數(shù)字類型),返回其2倍的值
x -> 2 * x

// 3. 接受2個(gè)參數(shù)(數(shù)字),并返回他們的差值
(x, y) -> x – y

// 4. 接收2個(gè)int型整數(shù),返回他們的和
(int x, int y) -> x + y

// 5. 接受一個(gè) string 對(duì)象,并在控制臺(tái)打印,不返回任何值(看起來(lái)像是返回void)
(String s) -> System.out.print(s)

Lambda表達(dá)式作用域

lambda表達(dá)式中可以引用任何外部的變量或者常量。但是對(duì)這些外部的變量是有要求的:它們必須是Effectively final的。

局部?jī)?nèi)部類和匿名內(nèi)部類訪問(wèn)的局部變量必須由final修飾,java8開始,可以不加final修飾符,由系統(tǒng)默認(rèn)添加。java將這個(gè)功能稱為:Effectively final功能。

方法引用

指向靜態(tài)方法的方法引用

Function<String, Integer> function1 = Integer::parseInt; // 等價(jià)于下面
Function<String, Integer> function2 = (String i) -> Integer.parseInt(i);

指向任意類型實(shí)例方法的方法引用

Function<String, String> function3 = String::toLowerCase; // 等價(jià)于下面
Function<String, String> function4 = (String i) -> i.toLowerCase();

BiFunction<String, Integer, String> biFunction = (String s, Integer i) -> s.substring(i);
BiFunction<String, Integer, String> biFunction2 = String::substring;

指向現(xiàn)有對(duì)象的實(shí)例方法的方法引用

String str = "hello";
Supplier<Integer> supplier = () -> str.length();
Supplier<Integer> supplier2 = str::length;

Function<Integer, String> function5 = (Integer i) -> str.substring(i);
Function<Integer, String> function6 = str::substring;

構(gòu)造方法引用

package com.morris.java8.lamdba;

import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;

public class MethodReferenceExample {

    public static void main(String[] args) {

        // 構(gòu)造函數(shù)引用
        Supplier<String> stringSupplier = () -> new String();
        Supplier<String> stringSupplier2 = String::new;

        Function<String, String> stringFunction = (String s)->new String(s);
        Function<String, String> stringFunction2 = String::new;

        BiFunction<Runnable, String, Thread> stringBiFunction = (Runnable r, String b)-> new Thread(r, b);
        BiFunction<Runnable, String, Thread> stringBiFunction2 = Thread::new;

        ThreeFunction<ThreadGroup, Runnable, String, Thread> threeFunction = (ThreadGroup g, Runnable r, String b)-> new Thread(g, r, b);
        ThreeFunction<ThreadGroup, Runnable, String, Thread> threeFunction2 = Thread::new;

    }

    interface ThreeFunction<A, B, C, D> {
        D triple(A a, B b, C c);
    }

}

lambda與匿名內(nèi)部類

從表面上看到Lambda表達(dá)式似乎只是為了簡(jiǎn)化匿名內(nèi)部類書寫,這看起來(lái)僅僅通過(guò)語(yǔ)法糖在編譯階段把所有的Lambda表達(dá)式替換成匿名內(nèi)部類就可以了。但實(shí)際并非如此。在JVM層面,Lambda表達(dá)式和匿名內(nèi)部類有著明顯的差別。

匿名內(nèi)部類

匿名內(nèi)部類仍然是一個(gè)類,只是不需要程序員顯示指定類名,編譯器會(huì)自動(dòng)為該類取名。

public class AnonymousClassDemo {

    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("this is an Anonymous class demo");
            }
        });
    }
}

因此上面的代碼,編譯之后將會(huì)產(chǎn)生兩個(gè)class文件:

AnonymousClassDemo.class
AnonymousClassDemo$1.class

進(jìn)一步分析主類AnonymousClassDemo.class的字節(jié)碼,可發(fā)現(xiàn)其創(chuàng)建了匿名內(nèi)部類的對(duì)象:

$ javap -v -p AnonymousClassDemo.class
...
  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=4, locals=1, args_size=1
         0: new           #2                  // class java/lang/Thread
         3: dup
         4: new           #3                  // class AnonymousClassDemo$1 創(chuàng)建匿名內(nèi)部類
         7: dup
         8: invokespecial #4                  // Method AnonymousClassDemo$1."<init>":()V
        11: invokespecial #5                  // Method java/lang/Thread."<init>":(Ljava/lang/Runnable;)V
        14: pop
        15: return
      LineNumberTable:
        line 5: 0
        line 11: 15
}
SourceFile: "AnonymousClassDemo.java"
InnerClasses:
     static #3; //class AnonymousClassDemo$1

lambda表達(dá)式

Lambda表達(dá)式通過(guò)invokedynamic指令實(shí)現(xiàn),不會(huì)產(chǎn)生新的類。

public class LambdaDemo {
    public static void main(String[] args) {
        new Thread(()-> System.out.println("this is a lambda demo"));
    }
}

上面的代碼編譯之后只有一個(gè)class文件:

LambdaDemo.class

通過(guò)javap查看LambdaDemo.class的字節(jié)碼,我們更能看出Lambda表達(dá)式內(nèi)部表示的不同。

$ javap -v -p LambdaDemo.class
...
  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=3, locals=1, args_size=1
         0: new           #2                  // class java/lang/Thread
         3: dup
         4: invokedynamic #3,  0              // InvokeDynamic #0:run:()Ljava/lang/Runnable; 使用invokedynamic指令調(diào)用
         9: invokespecial #4                  // Method java/lang/Thread."<init>":(Ljava/lang/Runnable;)V
        12: pop
        13: return
      LineNumberTable:
        line 4: 0
        line 5: 13

  private static void lambda$main$0(); // Lambda表達(dá)式被封裝成主類的私有方法
    descriptor: ()V
    flags: ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
    Code:
      stack=2, locals=0, args_size=0
         0: getstatic     #5                  // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #6                  // String this is a lambda demo
         5: invokevirtual #7                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         8: return
      LineNumberTable:
        line 4: 0
}
SourceFile: "LambdaDemo.java"
InnerClasses:
     public static final #51= #50 of #54; //Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
BootstrapMethods:
  0: #22 invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
    Method arguments:
      #23 ()V
      #24 invokestatic LambdaDemo.lambda$main$0:()V
      #23 ()V

反編譯之后我們發(fā)現(xiàn)Lambda表達(dá)式被封裝成了主類的一個(gè)私有方法,并通過(guò)invokedynamic指令進(jìn)行調(diào)用。

既然Lambda表達(dá)式不是內(nèi)部類的簡(jiǎn)寫,那么Lambda內(nèi)部的this引用也就跟內(nèi)部類對(duì)象沒什么關(guān)系了。在Lambda表達(dá)式中this的意義跟在表達(dá)式外部完全一樣。

總結(jié)

相同點(diǎn):

  • 都可以直接訪問(wèn)“effectively final”的局部變量(不需要加final關(guān)鍵字,但實(shí)際上是final,編譯器編譯時(shí)會(huì)自動(dòng)加上),以及外部類的成員變量(包括實(shí)例變量和類變量)。

不同點(diǎn):

  • 匿名內(nèi)部類可以為任意接口創(chuàng)建實(shí)例——不管接口包含多少個(gè)抽象方法,只要匿名內(nèi)部類實(shí)現(xiàn)所有的抽象方法即可。但Lambda表達(dá)式只能為函數(shù)式接口創(chuàng)建實(shí)例。
  • 匿名內(nèi)部類可以為抽象類、甚至普通類創(chuàng)建實(shí)例,但Lambda表達(dá)式只能為函數(shù)式接口創(chuàng)建實(shí)例。
  • 匿名內(nèi)部類實(shí)現(xiàn)的抽象方法的方法體允許調(diào)用接口中定義的默認(rèn)方法;但Lambda表達(dá)式的代碼塊不允許調(diào)用接口中定義的默認(rèn)方法。

到此這篇關(guān)于java8 lambda表達(dá)式簡(jiǎn)介的文章就介紹到這了,更多相關(guān)java8 lambda表達(dá)式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Spring中利用IOC實(shí)現(xiàn)注入的方式

    Spring中利用IOC實(shí)現(xiàn)注入的方式

    Spring IOC(控制反轉(zhuǎn))實(shí)現(xiàn)依賴注入,將對(duì)象創(chuàng)建和依賴關(guān)系的管理交由Spring容器處理,通過(guò)注解或XML配置,實(shí)現(xiàn)對(duì)象之間的松耦合,提高代碼復(fù)用性和可維護(hù)性
    2023-04-04
  • Spring Cloud Gateway 獲取請(qǐng)求體(Request Body)的多種方法

    Spring Cloud Gateway 獲取請(qǐng)求體(Request Body)的多種方法

    這篇文章主要介紹了Spring Cloud Gateway 獲取請(qǐng)求體(Request Body)的多種方法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-01-01
  • java日期時(shí)間格式化@JsonFormat與@DateTimeFormat的使用

    java日期時(shí)間格式化@JsonFormat與@DateTimeFormat的使用

    本文主要介紹了java日期時(shí)間格式化@JsonFormat與@DateTimeFormat的使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • 基于@Table注解無(wú)法使用及報(bào)紅的解決

    基于@Table注解無(wú)法使用及報(bào)紅的解決

    這篇文章主要介紹了基于@Table注解無(wú)法使用及報(bào)紅的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • IDEA快速搭建Java開發(fā)環(huán)境的教程圖解

    IDEA快速搭建Java開發(fā)環(huán)境的教程圖解

    這篇文章主要介紹了IDEA如何快速搭建Java開發(fā)環(huán)境,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-11-11
  • 淺析Java驗(yàn)證碼生成庫(kù)JCaptcha

    淺析Java驗(yàn)證碼生成庫(kù)JCaptcha

    JCaptcha 是一個(gè)用來(lái)生成驗(yàn)證碼的開源Java類庫(kù),使用起來(lái)也是非常的簡(jiǎn)單方便。本文通過(guò)代碼實(shí)例介紹了JCaptcha類庫(kù)。
    2016-07-07
  • 在Java的MyBatis框架中建立接口進(jìn)行CRUD操作的方法

    在Java的MyBatis框架中建立接口進(jìn)行CRUD操作的方法

    這篇文章主要介紹了在Java的MyBatis框架中建立接口進(jìn)行CRUD操作的方法,CRUD是指在做計(jì)算處理時(shí)的增加(Create)、重新取得數(shù)據(jù)(Retrieve)、更新(Update)和刪除(Delete)幾個(gè)單詞的首字母簡(jiǎn)寫,需要的朋友可以參考下
    2016-04-04
  • java數(shù)組及arrays類對(duì)數(shù)組的操作實(shí)例

    java數(shù)組及arrays類對(duì)數(shù)組的操作實(shí)例

    下面小編就為大家?guī)?lái)一篇java數(shù)組及arrays類對(duì)數(shù)組的操作實(shí)例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-10-10
  • 使用java采集京東商城區(qū)劃數(shù)據(jù)示例

    使用java采集京東商城區(qū)劃數(shù)據(jù)示例

    這篇文章主要介紹了java采集京東的全國(guó)區(qū)劃數(shù)據(jù)示例,保存成json形式,如想轉(zhuǎn)換到數(shù)據(jù)庫(kù)只需反序列化為對(duì)象保存到數(shù)據(jù)庫(kù)即可
    2014-03-03
  • java開源項(xiàng)目jeecgboot的超詳細(xì)解析

    java開源項(xiàng)目jeecgboot的超詳細(xì)解析

    JeecgBoot是一款基于BPM的低代碼平臺(tái),下面這篇文章主要給大家介紹了關(guān)于java開源項(xiàng)目jeecgboot的相關(guān)資料,文中通過(guò)圖文以及實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-10-10

最新評(píng)論