国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

關(guān)于對(duì)【java中的Lambda表達(dá)式】的理解與簡(jiǎn)述

這篇具有很好參考價(jià)值的文章主要介紹了關(guān)于對(duì)【java中的Lambda表達(dá)式】的理解與簡(jiǎn)述。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

【版權(quán)聲明】未經(jīng)博主同意,謝絕轉(zhuǎn)載?。ㄕ?qǐng)尊重原創(chuàng),博主保留追究權(quán))
https://blog.csdn.net/m0_69908381/article/details/130522535
出自【進(jìn)步*于辰的博客】

啟發(fā)博文:《Lambda表達(dá)式超詳細(xì)總結(jié)》(轉(zhuǎn)發(fā))。
這是我系統(tǒng)學(xué)習(xí)Lambda表達(dá)式時(shí)參考的文章。在下文中,我會(huì)引用這篇博文中的一些資源,如:圖片、闡述。因?yàn)槲艺J(rèn)為那位前輩總結(jié)的很好,我再盡力做也最多如此了。如有侵權(quán),請(qǐng)與我聯(lián)系!
參考筆記一,P33.8、P43.5;筆記三,P33.1。

注:掌握Lambda表達(dá)式,這兩個(gè)知識(shí)是基礎(chǔ):

  1. 匿名內(nèi)部類,幫助在于理解“ 變式 \color{red}{變式} 變式”,因?yàn)樽畛蹰_發(fā)Lambda表達(dá)式的目的之一是簡(jiǎn)化匿名內(nèi)部類;
  2. 泛型,用于Lambda表達(dá)式的“ 擴(kuò)展 \color{red}{擴(kuò)展} 擴(kuò)展”。

1、關(guān)于Lambda優(yōu)化匿名內(nèi)部類

1.1 內(nèi)部類

java中內(nèi)部類分為成員內(nèi)部類、靜態(tài)內(nèi)部類、局部?jī)?nèi)部類和匿名內(nèi)部類。

class TestInnerClass {
    // 成員內(nèi)部類
    class MemberInner {}
	
	// 靜態(tài)內(nèi)部類
    static class StaticInner {}

    public static void main(String[] args) {
		// 局部?jī)?nèi)部類
        class LocalInner {}

        // 匿名內(nèi)部類
        Runnable run = new Runnable() {
            public void run() {}
        };
        new Thread(run).start();
    }
}

與Lambda表達(dá)式相關(guān)的只有匿名內(nèi)部類。

1.2 匿名內(nèi)部類

示例:

Runnable runa = new Runnable() {
    public void run() {
    	sout "Hello!! CSDN";
    }
};
new Thread(runa).start();

等同于:

class MyRunnable implements Runnable {
    public void run() {
    	sout "Hello!! CSDN";
    }
}
class TestThread {
    public static void main(String[] args) {
        Runnable runa = new MyRunnable();
        new Thread(runa).start();
    }
}

匿名內(nèi)部類一般有一個(gè)特點(diǎn): 一次性 \color{red}{一次性} 一次性,故這種寫法既冗余,又 L O W LOW LOW。

使用 L a m b d a 進(jìn)行優(yōu)化: \color{red}{使用Lambda進(jìn)行優(yōu)化:} 使用Lambda進(jìn)行優(yōu)化:

Runnable runa = () -> {
    sout "Hello!! CSDN";
};
new Thread(runa).start();

有什么變化?是不是省去了run()的聲明部分。
繼續(xù)優(yōu)化。

new Thread(() -> {
    sout "Hello!! CSDN";
}).start();

這就是 “將函數(shù)如參數(shù)般傳遞” \color{red}{“將函數(shù)如參數(shù)般傳遞”} 將函數(shù)如參數(shù)般傳遞。大家先初步了解,繼續(xù)看。。。

題外話: 題外話: 題外話:
此項(xiàng)的第一個(gè)示例中的引用runa,指向 Runnable 接口的匿名內(nèi)部類(上轉(zhuǎn)),而下文所述的() -> {}和三種引用都可以說是對(duì)匿名內(nèi)部類的簡(jiǎn)化,但其已不是匿名內(nèi)部類,其類型是Lambda(一種類型)。
我暫未找到相關(guān)資料,就自己驗(yàn)證??聪率鍪纠?。

Predicate<Integer> ser1 = new Predicate<Integer>() {
    @Override
    public boolean test(Integer a) {
        return a.equals(0);
    }
};
Class z1 = ser1.getClass();
System.out.println(z1);// class Test2$1
System.out.println(z1.getSimpleName());// ""
System.out.println(z1.getEnclosingClass());// class Test2

Supplier<Integer> ser2 = () -> {
    return 0;
};
z1 = ser2.getClass();
System.out.println(z1);// class Test2$$Lambda$1/1791741888
System.out.println(z1.getSimpleName());// Test2$$Lambda$1/1791741888
System.out.println(z1.getEnclosingClass());// null

具體說明簡(jiǎn)單又啰嗦,就不贅述,大家只要了解getSimpleName()getEnclosingClass()這兩個(gè)方法就明白了。如果大家感興趣,可以看看我對(duì)Class<T>類的解析。

2、關(guān)于Lambda的優(yōu)化規(guī)范

2.1 準(zhǔn)備

從:

Runnable runa = new Runnable() {
    public void run() {
    	sout "Hello!! CSDN";
    }
};
new Thread(runa).start();

優(yōu)化為:

Runnable runa = () -> {
    sout "Hello!! CSDN";
};
new Thread(runa).start();

難道可以隨便寫?當(dāng)然不是。那規(guī)范是什么?

在上個(gè)例子中,大家有沒有注意一個(gè)問題? \color{grey}{在上個(gè)例子中,大家有沒有注意一個(gè)問題?} 在上個(gè)例子中,大家有沒有注意一個(gè)問題?
在示例中,有沒有run()的聲明?沒有。因此,Lambda只能優(yōu)化只有一個(gè)抽象方法的接口的匿名內(nèi)部類,這類接口稱之為 函數(shù)式接口 \color{green}{函數(shù)式接口} 函數(shù)式接口(注解是@FunctionalInterface)。

舉個(gè)例:定義java.lang.Number抽象類的匿名內(nèi)部類。
這是Number抽象類的源碼。
關(guān)于對(duì)【java中的Lambda表達(dá)式】的理解與簡(jiǎn)述

可見,有4個(gè)抽象方法。因此,創(chuàng)建 Number 類的匿名內(nèi)部類,必須重寫這4個(gè)抽象方法。即:

new Number() {
    @Override
    public int intValue() {
        return 0;
    }
    @Override
    public long longValue() {
        return 0;
    }
    ......
};

如這般,就無法使用 Lambda 進(jìn)行優(yōu)化。

2.2 規(guī)范

Lambda 的基礎(chǔ)語法:() -> {}。

->的左邊是圓括號(hào),對(duì)應(yīng)匿名內(nèi)部類重寫的唯一抽象方法的參數(shù)列表;右邊是花括號(hào),對(duì)應(yīng)方法體。

參數(shù)列表: \color{red}{參數(shù)列表:} 參數(shù)列表:

  1. 若無參,則必須是(),即:() -> {};
  2. 若只有1個(gè)參數(shù)xx,則可以是(xx)xx,即:(xx) -> {}xx -> {};(注:xx無類型,其名稱任意)
  3. 若有2個(gè)參數(shù) a 和 b,則必須是(a, b),即:(a, b) -> {};
  4. 舉一反三。

方法體: \color{red}{方法體:} 方法體:
由于方法體不用關(guān)注方法的聲明,故只注意一些 省略規(guī)范 省略規(guī)范 省略規(guī)范。

1、 若只有一條語句,可省略分號(hào)和花括號(hào)。
示例:

new Thread(() -> sout "Hello!! CSDN").start();
// 等同于:
new Thread(() -> {
	sout "Hello!! CSDN";
}).start();

run()無參。

2、 若方法有返回值,且只有一條語句時(shí),可省略分號(hào)、花括號(hào)和return。
示例:

interface SelfInterface {
    double getTrigonometric(double angle);
}

class TestSelf {
    public static void main(String[] args) {
        SelfInterface service = xx -> Math.sin(xx);
        // 等同于:
        SelfInterface service = xx -> {
            return Math.sin(xx);
        };
        
        double radian = service.getRadian(10);
        sout radian;// 打印:-0.5440211108893698
    }
}

2.3 補(bǔ)充說明

以上例為例:
關(guān)于對(duì)【java中的Lambda表達(dá)式】的理解與簡(jiǎn)述
兩個(gè)問題: \color{grey}{兩個(gè)問題:} 兩個(gè)問題:

  1. JVM如何知道圖中紅框部分是getTrigonometric()的方法體?
  2. JVM是如何知道參數(shù)xx的類型是double?(因?yàn)?code>Math.sin()的形參類型是 double)

下圖是Math.sin()的API截圖:
關(guān)于對(duì)【java中的Lambda表達(dá)式】的理解與簡(jiǎn)述
解釋: \color{red}{解釋:} 解釋: (以下闡述轉(zhuǎn)載自博文《Lambda表達(dá)式超詳細(xì)總結(jié)》)

因?yàn)镴VM可以通過上下文推斷出為何接口實(shí)現(xiàn)抽象方法,即 接口推斷 \color{purple}{接口推斷} 接口推斷;以及推斷出所實(shí)現(xiàn)的相應(yīng)抽象方法的參數(shù)列表(包括形參類型),即 類型推斷 \color{brown}{類型推斷} 類型推斷。
簡(jiǎn)言之,Lambda表達(dá)式依賴于上下文環(huán)境。

3、Java內(nèi)置函數(shù)式接口

3.1 四大核心函數(shù)式接口

(此表格引用自啟發(fā)博文。)

函數(shù)式接口 參數(shù)類型 返回值類型 說明
Consumer<T>消費(fèi)型接口 T void 對(duì)類型為T的對(duì)象應(yīng)用操作,包含方法:void accept(T t)
Supplier<T>供給型接口 T 返回類型為T的對(duì)象,包含方法:T get()
Function<T, R> T R 對(duì)類型為T的對(duì)象應(yīng)用操作,并返回類型為R的對(duì)象,包含方法:R apply(T t)
Predicate<T>斷定型接口 T boolean 斷定類型為T的對(duì)象是否滿足某約束,并返回boolean結(jié)果,包含方法:boolean test(T t)

使用示例:
1、消費(fèi)型接口 Consumer<T>

Consumer<String> service1 = str -> sout str;
service1.accept("Hello!! CSDN");// 打?。篐ello!! CSDN

方法:void accept(T t)。

2、供給型接口 Supplier<T>

Supplier<Integer> service2 = () -> (int)(Math.random() * 100);// 獲取0~100的隨機(jī)整數(shù)
sout service2.get();// 打印:66

方法:T get()。

3、函數(shù)型接口 Function<T,R>

Function<String, Integer> service3 = str -> str.length();
sout service3.apply("I love China!!");// 打?。?4

方法:R apply(T t)。

4、斷定型接口 Predicate<T>

Integer i1 = 10;
Predicate<Integer> service4 = xx -> i1.equals(xx);
sout service4.test(10);// 打印:true
sout service4.test(20);// 打?。篺alse

方法:boolean test(T t)。

3.2 其他函數(shù)式接口

(此表格引用自啟發(fā)博文。)

函數(shù)式接口 參數(shù)類型 返回值類型 說明
BiFunction<T, U, R> T, U R 對(duì)類型為T、U的對(duì)象應(yīng)用操作,返回類型為R的對(duì)象,包含方法:R apply(T t, U u)
UnaryOperator<T>Function<T>的子接口) T T 對(duì)類型為T的參數(shù)進(jìn)行一元運(yùn)算,并返回類型為T的結(jié)果,包含方法:T aaply(T t)
BinaryOperator<T>(BiFunction<T, U, R>的子接口) T, T T 對(duì)類型為T的參數(shù)進(jìn)行二元運(yùn)算,并返回類型為T的結(jié)果,包含方法:T apply(T t1, T t2)
BiConsumer<T, U> T, U void 對(duì)類型為T、U的對(duì)象應(yīng)用操作,包含方法:void accept(T t, U u)
ToIntFunction<T>ToLongFunction<T>、ToDoubleFunction<T> T int、long、double 分別計(jì)算 int、long、double 的函數(shù)
IntFunction<R>、LongFunction<R>、DoubleFunction<R> int、long、double R 參數(shù)分別為 int、long、double 的函數(shù)

使用示例:
1、函數(shù)型接口 BiFunction<T, U, R>

BiFunction<Character[], Character, Integer> service5 = (charArr, c) -> Arrays.binarySearch(charArr, c);
sout service5.apply(new Character[]{65, 66, 67}, 'B');// 打印:1

方法:R apply(T t, U u)。
關(guān)于binarySearch(),詳情可見Arrays類的第2.2項(xiàng)。

2、函數(shù)型接口 UnaryOperator<T>

UnaryOperator<String> service6 = str -> str.trim().split("!")[1].trim().toUpperCase();
sout service6.apply("   Hello KiTi! I am 小白 of csdn   ");// 打?。篒 AM 小白 OF CSDN

方法:T apply(T t)。

3、函數(shù)型接口 BinaryOperator<T>

BinaryOperator<List<Character>> service7 = (list1, list2) -> {
    Collections.copy(list2, list1);
    return list2;
};
sout service7.apply(Arrays.asList('C', 'h'), Arrays.asList('#', '#', 'i', 'n', 'a'));// 打?。篬C, h, i, n, a]

方法:T apply(T t1, T t2)。
關(guān)于copy(),詳情可見Collections類的第2.10項(xiàng);關(guān)于asList(),詳情可見 Arrays 類的第2.1項(xiàng)。

4、消費(fèi)型接口 BiConsumer<T,R>

BiConsumer<char[], Character>service8 = (charArr, c) -> {
    Arrays.fill(charArr, c);
    sout Arrays.toString(charArr);// 打?。篬#, #, #, #, #]
};
service8.accept(new char[]{'進(jìn)', '步', '*', '于', '辰'}, '#');

方法:void accept(T t, U u)
關(guān)于fill(),詳情可見 Arrays 類的第2.8項(xiàng)。

5、未知型接口 To[Int/Long?Double]Function<T>

// ToIntFunction<T>
ToIntFunction<List> service9= list -> list.size();
int size = service9.applyAsInt(Arrays.asList(true, 3, 2, 1, "yes", 'f', 'i', 'r', 'e'));// 結(jié)果:9

// ToLongFunction<T>
ToLongFunction<Integer> service10 = n-> {
    long startTime = System.nanoTime();
    while ((n--) > 0) {}
    long endTime = System.nanoTime();
    return endTime - startTime;
};
long time = service10.applyAsLong(100000);// 結(jié)果:6486400ms

// ToDoubleFunction<T>
ToDoubleFunction<Double> service11 = radian -> Math.toDegrees(radian);
double angle = service11.applyAsDouble(Math.PI);// 結(jié)果:180.0

方法:int/long/double applyAs[Int/Long/Double]

6、函數(shù)型接口 [Int/Long/Double]Function<R>

// IntFunction<R>
IntFunction<String> service12 = length -> {
    StringBuffer builder = new StringBuffer(10);
    while ((length--) > 0) {
        int x = (int) (Math.random() * 10);// 獲取0~9的隨機(jī)數(shù)
        builder.append(x);
    }
    return builder.toString();
};
String code = service12.apply(6);// 結(jié)果:695821

// LongFunction<R>
LongFunction<Date> service13 = timeStamp -> new Date(timeStamp);
Date current = service13.apply(System.currentTimeMillis());// 結(jié)果:Tue May 09 22:17:26 CST 2023

// DoubleFunction<R>
DoubleFunction<Long> service14 = originN -> Math.round(originN);
long round = service14.apply(10.5);// 結(jié)果:11

方法:R apply(int/long/double i)

3.3 其他函數(shù)式接口補(bǔ)充

函數(shù)式接口 參數(shù)類型 返回值類型 說明
斷定型接口 `BiPredicate<T, U> T, U boolean 確定類型分別為T/U的對(duì)象是否滿足某約束,并返回 boolean 值。包含方法:boolean test(T t, U u)

使用示例:
1、斷定型接口 `BiPredicate<T,U>:

BiPredicate<String, String > service1 = (t, u) -> t.equals(u);
sout service1.test("abc", "abc");// 打印:true
sout service1.test("abc", "123");// 打?。篺alse

方法:boolean test(T t, U u)。

3.4 示例補(bǔ)充說明

大家在看上面的示例時(shí),肯定想吐槽:“你寫的那些方法體,很多都是多此一舉?!?br> 以實(shí)用性的角度來說的確是,例如:sout strstr.length、xx > 0? true: false,直接調(diào)用相應(yīng)方法不香么?還用 Lambda 轉(zhuǎn)個(gè)彎實(shí)現(xiàn)。

那我為何還這樣寫? \color{grey}{那我為何還這樣寫?} 那我為何還這樣寫?
因?yàn)槲矣X得使用 Lambda 的核心思維在于 靈活、擴(kuò)展、通用 \color{red}{靈活、擴(kuò)展、通用} 靈活、擴(kuò)展、通用。因此,我寫那些示例的初衷是 “任意舉例、簡(jiǎn)單易懂” \color{green}{“任意舉例、簡(jiǎn)單易懂”} 任意舉例、簡(jiǎn)單易懂,目的不在于實(shí)現(xiàn)何種功能,而是闡述 Lambda 的使用。

4、Lambda表達(dá)式的三種引用

先言: \color{red}{先言:} 先言:
以下對(duì)于引用的示例,我會(huì)盡量用上文中Java內(nèi)置函數(shù)式接口及其所舉示例進(jìn)行 “演變” “演變” 演變舉例,從而降低大家閱讀代碼的成本。

4.1 方法引用

4.1.1 概述

先說結(jié)論: \color{red}{先說結(jié)論:} 先說結(jié)論:

方法引用中所使用的 “缺省參數(shù)列表” \color{red}{“缺省參數(shù)列表”} 缺省參數(shù)列表必須與抽象方法的參數(shù)列表相同,返回值類型也必須相同。

何為“缺省參數(shù)列表”? \color{grey}{何為“缺省參數(shù)列表”?} 何為缺省參數(shù)列表

“缺省參數(shù)列表”指方法引用中已指定參數(shù)與所引用方法的參數(shù)列表相比較的缺失參數(shù)部分。

這是我自定義的概念,看著有點(diǎn)繞口,我會(huì)在示例中舉例說明。

方法引用格式: \color{green}{方法引用格式:} 方法引用格式:

  1. 對(duì)象 :: 成員方法名;
  2. 類 :: 類方法名
  3. 類 :: 成員方法名。

4.1.2 說明示例

4.1.2.1 boolean equals(String str)

為 String 類的成員方法boolean equals(String str)定義方法引用。
以此例為基礎(chǔ)進(jìn)行舉例。

BiPredicate<String, String > service1 = (t, u) -> t.equals(u);

演變辦法一:

// 格式:類 :: 成員方法名
BiPredicate<String, String> service = String::equals;
sout service.test("csdn", "bilibili");// 打印:false
sout service.test("csdn", "csdn");// 打?。簍rue

為什么選擇 B i P r e d i c a t e 接口實(shí)現(xiàn)方法引用? \color{red}{為什么選擇 BiPredicate 接口實(shí)現(xiàn)方法引用?} 為什么選擇BiPredicate接口實(shí)現(xiàn)方法引用?

  1. equals()的返回值類型為 boolean,則此抽象方法的返回值類型也必須是 boolean;
  2. equals()是成員方法,一共需要2個(gè)變量,方法引用為String::equals,由于未指定任何變量,故缺省2個(gè)變量。而這兩個(gè)變量必須由抽象方法的參數(shù)列表提供,故參數(shù)列表必須且僅有兩個(gè)參數(shù),且類型要與方法引用的類型相同;
  3. equals()所需的兩個(gè)變量,類型都是 String,則抽象方法的兩個(gè)參數(shù)的類型只能是 String。故<T><U> 類型實(shí)參 \color{green}{類型實(shí)參} 類型實(shí)參為 String。

演變辦法二:

// 格式:對(duì)象 :: 成員方法名
String str = "csdn";
Predicate<String> service = str::equals;
sout service.test("bilibili");// 打?。篺alse
sout service.test("csdn");// 打?。簍rue

為什么選擇 P r e d i c a t e 接口實(shí)現(xiàn)方法引用? \color{red}{為什么選擇 Predicate接口實(shí)現(xiàn)方法引用?} 為什么選擇Predicate接口實(shí)現(xiàn)方法引用?

  1. equals()的返回值類型為 boolean,則此抽象方法的返回值類型也必須是 boolean;
  2. equals()是成員方法,一共需要2個(gè)變量,方法引用為str::equals,由于已指定一個(gè)變量,故缺省1個(gè)變量。而這兩個(gè)變量必須由抽象方法的參數(shù)列表提供,故參數(shù)列表必須且僅有一個(gè)參數(shù),且類型要與方法引用的類型相同;
  3. equals()所需的兩個(gè)變量,類型都是 String,則抽象方法的參數(shù)的類型只能是 String。故<T> 類型實(shí)參 \color{green}{類型實(shí)參} 類型實(shí)參為 String。
4.1.2.2 void fill()

為 Arrays 類的靜態(tài)方法void fill()定義方法引用。
以此例為基礎(chǔ)進(jìn)行舉例。

BiConsumer<char[], Character>service8 = (charArr, c) -> {
    Arrays.fill(charArr, c);
    sout Arrays.toString(charArr);// 打印:[#, #, #, #, #]
};
service8.accept(new char[]{'進(jìn)', '步', '*', '于', '辰'}, '#');

演變:

// 格式:類 :: 靜態(tài)方法名
BiConsumer<char[], Character> service8 = Arrays::fill;
char[] charArr = new char[]{'進(jìn)', '步', '*', '于', '辰'};
service8.accept(charArr, '#');
sout Arrays.toString(charArr);// 打?。篬#, #, #, #, #]

為什么選擇 B i C o n s u m e r 接口實(shí)現(xiàn)方法引用? \color{red}{為什么選擇 BiConsumer接口實(shí)現(xiàn)方法引用?} 為什么選擇BiConsumer接口實(shí)現(xiàn)方法引用?

  1. fill()無返回值,accept()也無返回值,故匹配;
  2. fill()是類方法,需要兩個(gè)變量,方法引用是Arrays::fill,由于未指定任何變量,故缺省2個(gè)變量。而這兩個(gè)變量必須由抽象方法的參數(shù)列表提供,故參數(shù)列表必須且僅有兩個(gè)參數(shù),且類型要與方法引用的類型相同;
  3. fill()的第1個(gè)參數(shù)類型為基本數(shù)據(jù)類型數(shù)組,為char[];第2個(gè)參數(shù)類型為基本數(shù)據(jù)類型,為char。這2個(gè)參數(shù)都由accept()提供,故<T> 類型實(shí)參 \color{green}{類型實(shí)參} 類型實(shí)參char[],<R> 類型實(shí)參 \color{blue}{類型實(shí)參} 類型實(shí)參為 Character,

留言: \color{purple}{留言:} 留言:
泛型的類型實(shí)參只能是,為何這里可以是char[](數(shù)組),歡迎各位博友在評(píng)論區(qū)討論??!

4.2 構(gòu)造器引用

4.2.1 概述

格式: \color{green}{格式:} 格式:類 :: new。

說明: \color{purple}{說明:} 說明:
顧名思義,“構(gòu)造器引用”的作用就是實(shí)例化,即返回實(shí)例。
例如:為實(shí)體類Users創(chuàng)建構(gòu)造器引用,則構(gòu)造器引用固定Users :: new,即返回一個(gè) Users 實(shí)例。

約束: \color{brown}{約束:} 約束:
抽象方法的參數(shù)列表決定了匹配哪個(gè)構(gòu)造方法,即構(gòu)造器引用等同于構(gòu)造方法。

4.2.2 示例

實(shí)體類。

class Users {
    private Integer id;
    private String[] hobby;

    public Users() {
    }

    public Users(Integer id) {
        this.id = id;
    }

    public Users(String[] hobby) {
        this.hobby = hobby;
    }

    public Users(Integer id, String[] hobby) {
        this.id = id;
        this.hobby = hobby;
    }
    
    @Override
    public String toString() {
        return "Users{" +
                "id=" + id +
                ", hobby=" + Arrays.toString(hobby) +
                '}';
    }
}

測(cè)試。

Supplier<Users> service1 = Users::new;
Users user1 = service1.get();
sout user1;// 打?。篣sers{id=null, hobby=null}

Function<Integer, Users> service2 = Users::new;
Users user2 = service2.apply(1001);
sout user2;// 打?。篣sers{id=1001, hobby=null}

Function<String[], Users> service3 = Users::new;
Users user3 = service3.apply(new String[]{"編程", "Game"});
sout user3;// 打?。篣sers{id=null, hobby=[編程, Game]}

BiFunction<Integer, String[], Users> service4 = Users::new;
Users user4 = service4.apply(1002, new String[]{"java", "cf"});
sout user4;// 打?。篣sers{id=1002, hobby=[java, cf]}

4.3 數(shù)組引用

格式: \color{orange}{格式:} 格式:類型[] :: new

說明: \color{dark}{說明:} 說明:
與構(gòu)造器引用同理。不過,數(shù)組引用返回的是數(shù)組。(我暫不知如何使用數(shù)組引用創(chuàng)建非空數(shù)組)

示例:

Function<Integer, Integer[]> service1 = Integer[]::new;
Integer[] arr = service1.apply(5);
sout Arrays.toString(arr);// 打?。篬null, null, null, null]

5、Lambda表達(dá)式的作用域

以下闡述轉(zhuǎn)載自博文《Lambda表達(dá)式超詳細(xì)總結(jié)》。

Lambda表達(dá)式可以看作是匿名內(nèi)部類實(shí)例化的對(duì)象,Lambda表達(dá)式對(duì)變量的訪問限制和匿名內(nèi)部類一樣。因此Lambda表達(dá)式可以訪問局部變量、局部引用,靜態(tài)變量和成員變量。

5.1 引用局部常量

規(guī)定在Lambda表達(dá)式中只能引用由final修飾的局部變量,即局部常量,包括局部基本類型常量和局部引用類型常量。

5.1.1 引用局部基本類型常量

double d1 = 10.2;-------------------------------------------A
// final double d1 = 10.2;----------------------------------------B
UnaryOperator<Double> service = d -> Math.floor(d + d1);----C
// d1 = 5.1;------------------------------------------------D
sout service.apply(5.9);// 打?。?6.0

d1定義為變量(A),可當(dāng)引用于 Lambda 中時(shí)(C),會(huì)隱式轉(zhuǎn)為常量,但當(dāng)為d1賦值時(shí)(D),這種“隱式轉(zhuǎn)換”功能會(huì)失效,d1仍為變量,則C會(huì)編譯報(bào)錯(cuò)。
若將d1顯式定義為常量(B),則C可編譯通過,但由于常量不可修改,D將會(huì)編譯報(bào)錯(cuò)。

5.1.2 引用局部引用類型常量

示例1:

String subStr = "csdn";
Predicate<String> service = str -> str.contains(subStr);
sout service.test("csdn, bilibili, 博客園");// 打?。簍rue
// subStr = "bili";

此示例與上文中【引用局部基本類型常量】的示例同理。

示例2:

List list = new ArrayList();
list.add(2023);
list.add("年");
list.add(5.12);
Supplier<Integer> service = () -> list.size();
sout service.get();// 打印:3
list.add(true);
sout service.get();// 打?。?

執(zhí)行list.add(true)是對(duì)list進(jìn)行了修改,按照上面的結(jié)論,這個(gè)示例是編譯報(bào)錯(cuò)的??蓪?shí)際上編譯通過。為什么?難道上面的結(jié)論有紕漏??
在后面加上這么一條代碼試試:

list = new ArrayList();

這樣就編譯報(bào)錯(cuò)了。大家看出來了吧。。。

結(jié)論: \color{red}{結(jié)論:} 結(jié)論:
由 Lambda 引用的局部常量不可修改,指的是不可修改引用指向

5.2 引用成員變量、類變量

public class TestReference {
	String originStr1 = "csdn,bilibili,博客園";
	static String originStr2 = "csdn,bilibili,博客園";
	
	public static void main(String[] args) {
	    Supplier<TestReference> service1 = TestReference::new;
	    TestReference t1 = service1.get();
	
	    Supplier<String[]> service2 = () -> t1.originStr1.split(",");
	    String[] arr1 = service2.get();-----------A
	    sout Arrays.toString(arr1);// 打?。篬csdn, bilibili, 博客園]
	    t1.originStr1 = "";-----------------------B
	
	    Supplier<String[]> service3 = () -> originStr2.split(",");
	    String[] arr2 = service3.get();-----------C
		sout Arrays.toString(arr2);// 打印:[csdn, bilibili, 博客園]
	    originStr2 = "";--------------------------D
	}
}

B、D處分別修改成員變量originStr1與類變量originStr2,都編譯通過??梢?,Lambda 不限制對(duì)成員變量和類變量的引用。

留言: \color{brown}{留言:} 留言:
至于 Lambda 有沒有如上文中【局部常量】般將成員變量或類變量隱式轉(zhuǎn)為常量,暫未可知。不過,我覺得沒有隱式轉(zhuǎn)換,因?yàn)锽、D處編譯通過。

5.3 引用成員常量、類常量

以上述【引用成員變量、類變量】的示例為基礎(chǔ),在成員變量originStr1和類變量originStr2的定義前加上final,即:

final String originStr1 = "csdn,bilibili,博客園";
final static String originStr2 = "csdn,bilibili,博客園";

則A、C處都編譯通過,說明,Lambda 不限制對(duì)成員常量和類常量的引用;而B、D處都編譯報(bào)錯(cuò)。這是常量本身的性質(zhì),與 Lambda 無關(guān)。

5.4 限制訪問局部變量的原因

具體原因,那位前輩已經(jīng)總結(jié)得很全面,我就不班門弄斧了,詳述請(qǐng)查閱博文《Lambda表達(dá)式超詳細(xì)總結(jié)》(轉(zhuǎn)發(fā))的第8.3項(xiàng)。

6、最后

本文中的示例是為了方便大家理解、以及闡述 Lambda 表達(dá)式的運(yùn)用而簡(jiǎn)單舉出的,不一定有實(shí)用性。示例很多,不過,我所舉的示例都是 “以簡(jiǎn)為宗旨” \color{green}{“以簡(jiǎn)為宗旨”} 以簡(jiǎn)為宗旨,重心不在于使用 Lambda 表達(dá)式編寫多么強(qiáng)大的功能,而在于盡量擴(kuò)展對(duì) Lambda 表達(dá)式的使用,讓大家能夠更透徹地理解它的格式、規(guī)范、限制等。

P S : \color{blue}{PS:} PS
這是我迄今為止寫過的內(nèi)容最多的一篇文章,超1.5萬字,我都有點(diǎn)佩服我自己。

當(dāng)然,這個(gè)內(nèi)容量與大神們動(dòng)則幾萬、十幾萬的大作相比,不值一提(我不是謙虛,類如幾萬、十幾萬的大作,那完全是上了另一個(gè)層面的文章了,用“論文”形容更貼切)。不過,我還是挺有成就感的且受益匪淺!

本文完結(jié)。文章來源地址http://www.zghlxwxcb.cn/news/detail-448849.html

到了這里,關(guān)于關(guān)于對(duì)【java中的Lambda表達(dá)式】的理解與簡(jiǎn)述的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 深入理解lambda表達(dá)式

    深入理解lambda表達(dá)式

    var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); app.Use(async (context, next) = { // Add code before request. }); 這段C#代碼是用于設(shè)置ASP.NET Core應(yīng)用中的中間件。下面是詳細(xì)解釋: app.Use : 這個(gè)方法是用來向應(yīng)用的請(qǐng)求處理管道中添加一個(gè)中間件的。在ASP.NET Core中,中間件用于處

    2024年02月20日
    瀏覽(30)
  • JAVA8-lambda表達(dá)式8:在設(shè)計(jì)模式-模板方法中的應(yīng)用

    JAVA8-lambda表達(dá)式1:什么是lambda表達(dá)式 JAVA8-lambda表達(dá)式2:常用的集合類api JAVA8-lambda表達(dá)式3:并行流,提升效率的利器? JAVA8-lambda表達(dá)式4:Optional用法 java8-lambda表達(dá)式5:toMap引發(fā)的線上故障 JAVA8-lambda表達(dá)式6:重構(gòu)和定制收集器 JAVA8-lambda表達(dá)式7:重要的函數(shù)接口 最近在公司

    2024年02月14日
    瀏覽(29)
  • C++ 中的Lambda表達(dá)式

    Lambda 表達(dá)式 (lambda expression)是一個(gè)匿名函數(shù),Lambda表達(dá)式基于數(shù)學(xué)中的λ演算得名,直接對(duì)應(yīng)于其中的lambda抽象(lambda abstraction),是 一個(gè)匿名函數(shù),即沒有函數(shù)名的函數(shù) 。Lambda表達(dá)式可以表示閉包(注意和數(shù)學(xué)傳統(tǒng)意義上的不同)。 閉包 就是能夠讀取其他函數(shù)內(nèi)部變量

    2024年02月09日
    瀏覽(22)
  • QT中的lambda表達(dá)式

    面是對(duì)Qt中在QObject::connect()中的lambda表達(dá)式常用用法 QString str(\\\"I am a string!\\\"); device=str; connect(ui- PushButton::clicked,[](bool){qDebug()\\\"device==\\\"device;}); 表達(dá)式詳解 a1 第一個(gè)參數(shù)含義 第一個(gè)參數(shù)ui-pushButton:表示對(duì)象; a2 第二個(gè)參數(shù)含義 第二個(gè)參數(shù)QPushButton::clicked:表示對(duì)象包含的信號(hào)(

    2024年02月04日
    瀏覽(20)
  • 探索Python中的函數(shù)式編程:Lambda表達(dá)式與函數(shù)式工具【第135篇—Lambda表達(dá)式】

    探索Python中的函數(shù)式編程:Lambda表達(dá)式與函數(shù)式工具【第135篇—Lambda表達(dá)式】

    前些天發(fā)現(xiàn)了一個(gè)巨牛的人工智能學(xué)習(xí)網(wǎng)站,通俗易懂,風(fēng)趣幽默,忍不住分享一下給大家。【點(diǎn)擊進(jìn)入巨牛的人工智能學(xué)習(xí)網(wǎng)站】。 在Python編程世界中,函數(shù)式編程逐漸成為了一種流行的范式,特別是在處理數(shù)據(jù)和編寫簡(jiǎn)潔、高效代碼時(shí)。函數(shù)式編程的核心思想是將計(jì)算視

    2024年04月08日
    瀏覽(33)
  • 進(jìn)階JAVA篇- Lambda 表達(dá)式與 Lambda 表達(dá)式的省略規(guī)則

    進(jìn)階JAVA篇- Lambda 表達(dá)式與 Lambda 表達(dá)式的省略規(guī)則

    目錄 ? ? ? ? 1.0 什么是 Lambda 表達(dá)式? ? ? ? ? 1.1 既然跟匿名內(nèi)部類相關(guān),先來回顧匿名內(nèi)部類。 ? ? ? ? ?1.2 Lambda 表達(dá)式與匿名內(nèi)部類之間的關(guān)系。 ? ? ? ? 1.3 函數(shù)式接口 ? ? ? ? 1.4 在具體代碼中來操作一下 ? ? ? ? 2.0?Lambda 表達(dá)式省略規(guī)則 ??????? ?Lambda 表達(dá)

    2024年02月08日
    瀏覽(29)
  • Java- Lambda表達(dá)式

    目錄 一、Lambda簡(jiǎn)介 二、Lambda使用前提 三、Lambda語法 1.操作符 a.\\\"-\\\" ?b.\\\"::\\\" 2.格式? a.無參數(shù) b.有參數(shù) 四、Lambda演化過程 五、Lambda實(shí)現(xiàn)排序 Lambda 表達(dá)式,也可稱為閉包,它是推動(dòng) Java 8 發(fā)布的最重要新特性。Lambda 允許把函數(shù)作為一個(gè)方法的參數(shù)(函數(shù)作為參數(shù)傳遞進(jìn)方法中)

    2024年02月03日
    瀏覽(28)
  • Java Lambda表達(dá)式

    1.1 函數(shù)式編程思想概括 在數(shù)學(xué)中,函數(shù)就是有輸入量、輸出量的一套計(jì)算方案,也就是“拿數(shù)據(jù)做操作” 面向?qū)ο笏枷霃?qiáng)調(diào)“必須通過對(duì)象的形式來做事情” 函數(shù)式思想則盡量忽略面

    2024年02月07日
    瀏覽(42)
  • Java Lambda 表達(dá)式

    Java Lambda 表達(dá)式

    ??wei_shuo的個(gè)人主頁(yè) ??wei_shuo的學(xué)習(xí)社區(qū) ??Hello World ! Java Lambda 表達(dá)式是 Java 8 引入的一種函數(shù)式編程特性,它是一種輕量級(jí)的匿名函數(shù),允許我們將函數(shù)作為方法的參數(shù)進(jìn)行傳遞。Lambda 表達(dá)式可以理解為是一種簡(jiǎn)潔的方式來表示可傳遞的代碼塊,它可以替代傳統(tǒng)的匿名內(nèi)

    2024年02月08日
    瀏覽(34)
  • Lambda表達(dá)式(JAVA)

    Lambda表達(dá)式(JAVA)

    注:如果沒有學(xué)過 匿名內(nèi)部類 和 接口 不推薦往下看。 (parameters) - expression 或 (parameters) -{ statements; } parameters:表示參數(shù)列表; -:可理解為“被用于”的意思; expression:表示一條語句; statements:表示多條語句。 Lambda可以理解為:Lambda就是匿名內(nèi)部類的簡(jiǎn)化。 lambda表達(dá)式

    2024年02月08日
    瀏覽(28)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包