成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Java8 Lamda詳解

anquan / 1541人閱讀

摘要:局部變量表達(dá)式的方法體與嵌套代碼塊有著相同的作用域。在表達(dá)式中不允許聲明一個(gè)與局部變量同名的參數(shù)或者局部變量。不可變的約束只作用在局部變量上,如果是一個(gè)實(shí)例變量或者閉合類的靜態(tài)變量,那么不會(huì)有任何錯(cuò)誤被報(bào)告出來(lái)即使結(jié)果同樣未定義。

完整的Java學(xué)習(xí)的路線圖可以參考:我的編程之路--知識(shí)管理與知識(shí)體系

Lambda&Closures

Java8 Lambda表達(dá)式10個(gè)示例

閉包一般指存在自由變量的代碼塊,它與對(duì)象類似,都是用來(lái)描述一段代碼與其環(huán)境的關(guān)系。在Java中,Lambda表達(dá)式就是閉包。事實(shí)上,內(nèi)部類一直都是閉包,而Java8中為閉包賦予了更吸引人的語(yǔ)法。一個(gè)Lambda表達(dá)式包括三個(gè)部分:

一段代碼

參數(shù)

自由變量的值,這里的“自由”指的是那些不是參數(shù)并且沒有在代碼中定義的變量。

Lambda表達(dá)式本身是構(gòu)造了一個(gè)繼承自某個(gè)函數(shù)式接口的子類,所以可以用父類指針指向它。Java中本質(zhì)上閉包中是采用的值捕獲,即不可以在閉包中使用可變對(duì)象。但是它實(shí)際上是允許捕獲事實(shí)上不變量,譬如不可變的ArrayList,只是指針指向不可變罷了。雖然實(shí)現(xiàn)用的是值捕獲,但效果看起來(lái)跟引用捕獲一樣;就算以后的Java擴(kuò)展到允許通用的(對(duì)可變變量的)引用捕獲,也不會(huì)跟已有的代碼發(fā)生不兼容。

Java中最常見的閉包的使用如下所示:

Runnable task = () -> {
    // do something
};

Comparator cmp = (s1, s2) -> {
    return Integer.compare(s1.length(), s2.length());
};
方法引用

有時(shí)候Lambda表達(dá)式的代碼就只是一個(gè)簡(jiǎn)單的方法調(diào)用而已,遇到這種情況,Lambda表達(dá)式還可以進(jìn)一步簡(jiǎn)化為 方法引用(Method References) 。一共有四種形式的方法引用。

(1)靜態(tài)方法引用

List ints = Arrays.asList(1, 2, 3);
ints.sort(Integer::compare);

(2)某個(gè)特定對(duì)象的實(shí)例方法

例如前面那個(gè)遍歷并打印每一個(gè)word的例子可以寫成這樣:

words.forEach(System.out::println);

(3)某個(gè)類的實(shí)例方法

例如:

words.stream().map(word -> word.length()); // lambda
words.stream().map(String::length); // method reference

(4)構(gòu)造函數(shù)引用

// lambda
words.stream().map(word -> {
    return new StringBuilder(word);
});
// constructor reference
words.stream().map(StringBuilder::new);
Variable Scope(變量作用域)

在Lambda中,變量的作用域與訪問(wèn)操作主要遵循以下規(guī)則:

本地變量(Local Variable)可以訪問(wèn)但是不可以修改。

類成員變量與靜態(tài)變量可以被讀寫,即閉包中的this實(shí)際指向的是創(chuàng)建該Lambda表達(dá)式的方法的this參數(shù)。

函數(shù)式接口的默認(rèn)方法不可以在Lambda表達(dá)式中被訪問(wèn)。

(1)局部變量
lambda表達(dá)式的方法體與嵌套代碼塊有著相同的作用域。因此它也適用同樣的命名沖突和屏蔽規(guī)則。在lambda表達(dá)式中不允許聲明一個(gè)與局部變量同名的參數(shù)或者局部變量。

Path first = Paths.get("/usr/bin");
Comparator comp = (first,second) ->
    Integer.compare(first.length(),second.length());
//錯(cuò)誤,變量first已經(jīng)定義了

在一個(gè)方法里,你不能有兩個(gè)同名的局部變量,因此,你也不能在lambda表達(dá)式中引入這樣的變量。在下一個(gè)示例中,lambda表達(dá)式有兩個(gè)自由變量,text和count。數(shù)據(jù)結(jié)構(gòu)表示lambda表達(dá)式必須存儲(chǔ)這兩個(gè)變量的值,即“Hello”和20。我們可以說(shuō),這些值已經(jīng)被lambda表達(dá)式捕獲了(這是一個(gè)技術(shù)實(shí)現(xiàn)的細(xì)節(jié)。例如,你可以將一個(gè)lambda表達(dá)式轉(zhuǎn)換為一個(gè)只含一個(gè)方法的對(duì)象,這樣自由變量的值就會(huì)被復(fù)制到該對(duì)象的實(shí)例變量中)。

package java8test;

public class T1 {
    public static void main(String[] args) {
        repeatMessage("Hello", 20);
    }
    public static void repeatMessage(String text,int count){
        Runnable r = () -> {
            for(int i = 0; i < count; i++){
                System.out.println(text);
                Thread.yield();
            }
        };
        new Thread(r).start();
    }
}

(2)this

當(dāng)你在lambda表達(dá)式中使用this關(guān)鍵字,你會(huì)引用創(chuàng)建該lambda表達(dá)式的方法的this參數(shù),以下面的代碼為例:

public class Application{
    public void doWork(){
        Runnable runner = () -> {....;System.out.println(this.toString());......};
    }
}

表達(dá)式this.toString()會(huì)調(diào)用Application對(duì)象的toString()方法,而不是Runnable實(shí)例的toString()方法。在lambda表達(dá)式中使用this,與在其他地方使用this沒有什么不同。lambda表達(dá)式的作用域被嵌套在doWork()方法中,并且無(wú)論this位于方法的何處,其意義都是一樣的。

(3)引用的變量不可更改

Lambda表達(dá)式可以捕獲閉合作用域中的變量值。在Java中,為了確保被捕獲的值是被良好定義的,需要遵守一個(gè)重要的約束。在lambda表達(dá)式中,被引用的變量的值不可以被更改。例如,下面這個(gè)表達(dá)式是不合法的:

public static void repeatMessage(String text,int count){
    Runnable r = () -> {
        while(count > 0){
            count--;        //錯(cuò)誤,不能更改已捕獲變量的值
            System.out.println(text);
            Thread.yield();
         }
     };
     new Thread(r).start();
}

做出這個(gè)約束是有原因的。更改lambda表達(dá)式中的變量不是線程安全的。假設(shè)有一系列并發(fā)的任務(wù),每個(gè)線程都會(huì)更新一個(gè)共享的計(jì)數(shù)器。

int matches = 0;
for(Path p : files)
    new Thread(() -> {if(p中包含某些屬性) matches++;}).start();    //非法更改matches的值

如果這段代碼是合法的,那么會(huì)引起十分糟糕的結(jié)果。自增操作matches++不是原子操作,如果多個(gè)線程并發(fā)執(zhí)行該自增操作,天曉得會(huì)發(fā)生什么。不要指望編譯器會(huì)捕獲所有并發(fā)訪問(wèn)錯(cuò)誤。不可變的約束只作用在局部變量上,如果matches是一個(gè)實(shí)例變量或者閉合類的靜態(tài)變量,那么不會(huì)有任何錯(cuò)誤被報(bào)告出來(lái)即使結(jié)果同樣未定義。同樣,改變一個(gè)共享對(duì)象也是完全合法的,即使這樣并不恰當(dāng)。例如:

List matches = new ArrayList<>();
for(Path p: files)
//你可以改變matches的值,但是在多線程下是不安全的
    new Thread(() -> {if(p中包含某些屬性) matches.add(p);}).start();

注意matches是“有效final”的(一個(gè)有效的final變量被初始化后,就永遠(yuǎn)不會(huì)再被賦一個(gè)新值的變量)。在我們的示例中,matches總是引用同一個(gè)ArrayList對(duì)象,但是,這個(gè)對(duì)象是可變的,因此是線程不安全的 。如果多個(gè)線程同時(shí)調(diào)用add方法,結(jié)果將無(wú)法預(yù)測(cè)。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/65627.html

相關(guān)文章

  • Java8的新特性

    摘要:語(yǔ)言特性系列的新特性的新特性的新特性的新特性的新特性的新特性的新特性的新特性的新特性序本文主要講的新特性,也是一個(gè)重要的版本,在語(yǔ)法層面有更大的改動(dòng),支持了表達(dá)式,影響堪比的泛型支持。 Java語(yǔ)言特性系列 Java5的新特性 Java6的新特性 Java7的新特性 Java8的新特性 Java9的新特性 Java10的新特性 Java11的新特性 Java12的新特性 Java13...

    xi4oh4o 評(píng)論0 收藏0
  • Java學(xué)習(xí)路線總結(jié),搬磚工逆襲Java架構(gòu)師(全網(wǎng)最強(qiáng))

    摘要:哪吒社區(qū)技能樹打卡打卡貼函數(shù)式接口簡(jiǎn)介領(lǐng)域優(yōu)質(zhì)創(chuàng)作者哪吒公眾號(hào)作者架構(gòu)師奮斗者掃描主頁(yè)左側(cè)二維碼,加入群聊,一起學(xué)習(xí)一起進(jìn)步歡迎點(diǎn)贊收藏留言前情提要無(wú)意間聽到領(lǐng)導(dǎo)們的談話,現(xiàn)在公司的現(xiàn)狀是碼農(nóng)太多,但能獨(dú)立帶隊(duì)的人太少,簡(jiǎn)而言之,不缺干 ? 哪吒社區(qū)Java技能樹打卡?【打卡貼 day2...

    Scorpion 評(píng)論0 收藏0
  • Java Optional 實(shí)踐

    摘要:實(shí)踐很簡(jiǎn)單的一個(gè)類,點(diǎn)開它的源代碼,其中所有的方法都是與相關(guān)聯(lián)的。從而很好地避免了空指針異常。方法,如果存在,返回包含的值,否則拋出異常。隨便點(diǎn)開一個(gè)方法,都會(huì)在第一行為不該為的參數(shù)進(jìn)行判斷。 問(wèn)題描述 在大熱的Spring Boot 2.0中,在將原來(lái)的泛型改為了Optional,旨在讓我們的代碼更簡(jiǎn)潔。 showImg(https://segmentfault.com/img/bV...

    jaysun 評(píng)論0 收藏0
  • Python3,68個(gè)內(nèi)置庫(kù)函數(shù)詳解,進(jìn)階必備,必須收藏??!!

    摘要:判斷奇數(shù)是迭代器會(huì)根據(jù)提供的函數(shù)對(duì)指定序列做映射語(yǔ)法可以對(duì)可迭代對(duì)象中的每一個(gè)元素進(jìn)行映射。 python內(nèi)置庫(kù)詳解 1、引言2、內(nèi)置庫(kù)詳解2.1 數(shù)據(jù)相關(guān)2.1...

    lindroid 評(píng)論0 收藏0
  • Java8-5-Function函數(shù)式接口進(jìn)階與默認(rèn)方法詳解

    摘要:函數(shù)式接口進(jìn)階與默認(rèn)方法詳解上一篇我們快速的借助示例演示了的簡(jiǎn)單應(yīng)用,體會(huì)到了使用對(duì)集合處理的便捷和其與函數(shù)式接口密不可分的關(guān)系,所以為了更高效的使用,有必要更熟練的掌握函數(shù)式接口。 Java8-5-函數(shù)式接口進(jìn)階與默認(rèn)方法詳解上一篇我們快速的借助示例演示了stream api的簡(jiǎn)單應(yīng)用,體會(huì)到了使用stream api對(duì)集合處理的便捷和其與函數(shù)式接口密不可分的關(guān)系,所以為了更高效的使...

    Miracle_lihb 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<