国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Java Lambda 表達(dá)式(又名閉包 (Closure)/ 匿名函數(shù) ) 筆記

fou7 / 2675人閱讀

摘要:表達(dá)式又名閉包匿名函數(shù)筆記根據(jù)終于在中引入了表達(dá)式。函數(shù)式接口要介紹中表達(dá)式的實(shí)現(xiàn),需要知道什么是函數(shù)式接口。但同樣需要保證外部的自由變量不能在表達(dá)式中被改變。

Java Lambda 表達(dá)式(又名閉包 (Closure)/ 匿名函數(shù) ) 筆記

根據(jù) JSR 335, Java 終于在 Java 8 中引入了 Lambda 表達(dá)式。也稱之為閉包或者匿名函數(shù)。

JSR 335

所謂的 JSR (Java Specification Requests) 全稱叫做 Java 規(guī)范提案。簡(jiǎn)單來(lái)說(shuō)就是向 Java 社區(qū)提交新的 API 或 服務(wù) 請(qǐng)求的提案。這些提案將作為 Java 社區(qū)進(jìn)行 Java 語(yǔ)言開(kāi)發(fā)的需求,引導(dǎo)著開(kāi)發(fā)的方向。

JSR 335 的提案內(nèi)容摘要如下:

This JSR will extend the Java Programming Language Specification and the Java Virtual Machine Specification to support the following features:

ambda Expressions

SAM Conversion

Method References

Virtual Extension Methods

也就是如下幾點(diǎn):

支持 lambda 表達(dá)式。

支持 SAM conversion 用來(lái)向前兼容。

方法引用 Method References

Virtual Extension Methods

在 Java 8 中,以上均已經(jīng)實(shí)現(xiàn), 以上內(nèi)容下文均有介紹。

為什么需要 Lambda 表達(dá)式?

Lambda 表達(dá)式,其實(shí)就是代碼塊。

原來(lái)怎么處理

在具體了解 lambda 之前,我們先往后退一步,看看之前我們是如何處理這些代碼塊的!

例子一

當(dāng)決定在多帶帶的線程運(yùn)行某程序時(shí),你這樣做的

class Worker implements Runnable {
     public void run() {
        for (int i = 0; i < 1000; i++)
           doWork();
     }
     ...
  }
  

這樣執(zhí)行:

Worker w = new Worker();
new Thread(w).start();

Worker 中包含了你要執(zhí)行的代碼塊。

例子二

如果你想實(shí)現(xiàn)根據(jù)字符串長(zhǎng)度大小來(lái)排序,而不是默認(rèn)的字母順序,你可以自己來(lái)實(shí)現(xiàn)一個(gè) Comparator 用來(lái) Sort

class LengthComparator implements Comparator {
     public int compare(String first, String second) {
        return Integer.compare(first.length(), second.length());
     }
  }
   
Arrays.sort(strings, new LengthComparator());

####例子三

另外一個(gè)例子,我選的是 Android 中的點(diǎn)擊事件,同樣是 Java:

button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        Toast.makeText(MainActivity.this, "Hello World!", Toast.LENGTH_SHORT).show();
    }
});

###上面代碼有什么問(wèn)題呢?###

它們都太復(fù)雜了啊!

上述例子都是在某個(gè)類中實(shí)現(xiàn)某個(gè)接口,然后傳遞到另外一個(gè)方法中作為參數(shù),然后用來(lái)執(zhí)行。

但是本質(zhì)上,他們要傳遞的就是接口中那一個(gè)方法的實(shí)現(xiàn)而已啊!有必要先創(chuàng)建類,再實(shí)例化,再傳遞給調(diào)用的位置嗎?

因?yàn)?Java 是純面向?qū)ο蟮恼Z(yǔ)言,像其他語(yǔ)言那樣隨隨便便傳個(gè)方法過(guò)來(lái),那可不行,必須要這樣。
在其他語(yǔ)言中你可能可以,但是,在Java 中,不可以。

Java 設(shè)計(jì)人員為了 Java 的簡(jiǎn)潔跟連貫性,一直拒絕為 Java 添加這種功能。(這也是我喜歡 Java 而不喜歡 Python 的原因啊!!!)

經(jīng)過(guò)多年的努力,開(kāi)發(fā)人員終于找到了符合 Java 編程習(xí)慣的 Lambda 表達(dá)式!

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

考慮下前面的例子:

Integer.compare(first.length(), second.length())

first 和 second 都是 String 類型,Java 是強(qiáng)類型的語(yǔ)言,必須指定類型:

(String first, String second)
 -> Integer.compare(first.length(), second.length())

看到?jīng)]有!第一個(gè) Lambda 表達(dá)式誕生了!!輸入、輸出簡(jiǎn)潔明了!

為什么叫 Lambda 呢,這個(gè)很多年以前,有位邏輯學(xué)家想要標(biāo)準(zhǔn)化的表示一些可以被計(jì)算的數(shù)學(xué)方程(實(shí)際上存在,但是很難被表示出來(lái)),他就用 ? 來(lái)表示。

重新介紹一下 Java 中 Lambda 表達(dá)式的格式:

(參數(shù)) -> 表達(dá)式

多返回值
(String first, String second) -> {
 if (first.length() < second.length()) return -1;
 else if (first.length() > second.length()) return 1;
 else return 0;

}

如果計(jì)算的結(jié)果并不由一個(gè)單一的表達(dá)式返回(換言之,返回值存在多種情況),使用“{}”,然后明確指定返回值。

(String first, String second) -> {
     if (first.length() < second.length()) return -1;
     else if (first.length() > second.length()) return 1;
     else return 0;
}

###無(wú)參數(shù)

如果沒(méi)有參數(shù),則 “()”中就空著。

() -> { for (int i = 0; i < 1000; i++) doWork(); }

###省略###

Comparator comp
 = (first, second) // Same as (String first, String second)
    -> Integer.compare(first.length(), second.length());

這里,first 和 second 可以被推斷出是 String 類型,因?yàn)?是一個(gè) String 類型的 Comparator。

如果單個(gè)參數(shù)可以被推斷出,你連括號(hào)都可以省略:

EventHandler listener = event ->
 System.out.println("Thanks for clicking!");
    // Instead of (event) -> or (ActionEvent event) ->

###修飾符

你可以像對(duì)待其他方法一樣,annotation,或者 使用 final 修飾符

(final String name) -> ...
    (@NonNull String name) -> ...

永遠(yuǎn)不要 定義 result 的類型,lambda 表達(dá)式總是從上下文中推斷出來(lái)的:

(String first, String second) -> Integer.compare(first.length(), second.length())

###注意
注意,在 lambda 表達(dá)式中,某些分支存在返回值,某些不存在返回值這樣的情況是不允許的。
(int x) -> {if (x >= 0) return 1; }這樣是非法的。

函數(shù)式接口 (Functional Interfaces/SAM)

要介紹 Java 中 lambda 表達(dá)式的實(shí)現(xiàn),需要知道什么是 函數(shù)式接口。

什么叫作函數(shù)式接口呢 (SAM)?

函數(shù)式接口指的是只定義了唯一的抽象方法的接口(除了隱含的 Object 對(duì)象的公共方法), 因此最開(kāi)始也就做 SAM 類型的接口(Single Abstract Method)。

Lambda 表達(dá)式 向前兼容 這些接口。

Comparable

舉個(gè)例子 Array.sort:

Arrays.sort(words,
     (first, second) -> Integer.compare(first.length(), second.length()));

Array.sort() 方法收到一個(gè)實(shí)現(xiàn)了 Comparable接口的實(shí)例。

其實(shí)可以把 Lambda 表達(dá)式想象成一個(gè)方法,而非一個(gè)對(duì)象,一個(gè)可以傳入一個(gè)接口的方法。

OnClickListener

再舉個(gè)例子

button.setOnClickListener(event ->
 System.out.println("Thanks for clicking!"));

你看,是不是更易讀了呢?

Lambda 表達(dá)式能夠向前兼容這些 interfaces, 太棒了! 那 Lambda 表達(dá)式還能干什么呢?

實(shí)際上,將函數(shù)式接口轉(zhuǎn)變成 lambda 表達(dá)式是你在 Java 中 唯一 能做的事情。


Why ?!!

在其他的語(yǔ)言中,你可以定義一些方便的方法類型,但在 Java 中,你甚至不能將一個(gè) Lambda 表達(dá)式賦值給類型為 Object 的變量,因?yàn)?Object 變量不是一個(gè) Functional Interface。

Java 的設(shè)計(jì)者們堅(jiān)持使用熟悉的 interface 概念而不是為其引入新的 方法類型。

(這里我還要為設(shè)計(jì)者點(diǎn)贊!謹(jǐn)慎的設(shè)計(jì),一方面降低了初學(xué)者的門檻,一方面方便了高級(jí)用戶的使用。對(duì)比 python2 和 python3,升級(jí)的不兼容讓很多人一直停留在 python2)

Method References

能不能再簡(jiǎn)潔一點(diǎn)?有的時(shí)候我們所要做的事情不過(guò)是調(diào)用其他類中方法來(lái)處理事件。

button.setOnClickListener(event -> System.out.println(event));

如果這樣呢?

button.setOnAction(System.out::println);

表達(dá)式 System.out::println 屬于一個(gè)方法引用(method reference), 相當(dāng)于 lambda 表達(dá)式 x -> System.out.println(x)

再舉個(gè)例子,如果你想對(duì)字符串不管大小寫(xiě)進(jìn)行排序, 就可以這樣寫(xiě)!

Arrays.sort(strings, String::compareToIgnoreCase)

如上所見(jiàn) ::操作符將方法名與實(shí)例或者類分隔開(kāi)。總體來(lái)說(shuō),又如下的規(guī)則:

object::instanceMethod

Class::staticMethod

Class::instanceMethod

值得指出的是, thissuper 關(guān)鍵字可以在其中使用:

 class Greeter {
     public void greet() {
        System.out.println("Hello, world!");
     }
  }     

.

 class ConcurrentGreeter extends Greeter {
 public void greet() {
    Thread t = new Thread(super::greet);
    t.start();
 }
}
構(gòu)造方法引用 Constructor References

跟上一個(gè)差不多,畢竟 構(gòu)造方法 也是方法啊!!不過(guò)方法名字為 new 。

但是!這個(gè)構(gòu)造方法引用有一個(gè)牛逼的地方!

你知道 Array 是不能使用范型的對(duì)吧!(什么,你不知道?看看這里 http://stackoverflow.com/ques... 你沒(méi)有辦法創(chuàng)建一個(gè)類型為 T 的 Array 。 new T[n] 將會(huì)被覆蓋為 new Object[n]。

假設(shè)我們想要一個(gè)包含 buttons 的 Array。Stream interface 可以返回一個(gè) Object array。

Object[] buttons = stream.toArray();

不不不,我們可不想要 Object。Stream 庫(kù)使用 構(gòu)造方法引用解決了這個(gè)問(wèn)題:

Button[] buttons = stream.toArray(Button[]::new);

變量作用域

注意到我們?cè)陬}目中寫(xiě)著 閉包(closure), 實(shí)際上,閉包的定義是: 引用了自由變量的函數(shù)。

在之前,如果需要在匿名類的內(nèi)部引用外部變量,需要將外部變量定義為 final ,現(xiàn)在有了 lambda 表達(dá)式,你不必再這么做了。但同樣需要保證外部的自由變量不能在 lambda 表達(dá)式中被改變。

這是什么意思呢? 不需要定義為 final,也不能改?

其實(shí)理解起來(lái)很簡(jiǎn)單,Java 8 中,不需要定義為 final ,但你其實(shí)可以直接把他當(dāng)作 final,不要試圖修改它就行了。

即便你用內(nèi)部類,現(xiàn)在也無(wú)需定義為 final 了。

參考 StackOverFlow 鏈接: http://stackoverflow.com/ques...

Default Methods

由于歷史原因,像是類似 Collection 這種接口,如果進(jìn)行添加接口的話,那將會(huì)造成之前的代碼出錯(cuò)。

Java 想了一個(gè)一勞永逸的方法解決這個(gè)問(wèn)題, 使用 default 修飾符來(lái)提供默認(rèn)的實(shí)現(xiàn)

比如 Collection 接口的源代碼:

default void remove() {
     throw new UnsupportedOperationException("remove");
}

當(dāng)沒(méi)有 override remove 這個(gè)方法是,調(diào)用的時(shí)候返回 UnsupportedOperationException 錯(cuò)誤。

Static Methods in Interfaces

Java 8 中,你可以在接口中添加靜態(tài)方法了。 看起來(lái)好像并不符合接口的定義了。

一般用來(lái)生成一個(gè)簡(jiǎn)單實(shí)現(xiàn)該 interface 的實(shí)例。

參考鏈接:

JSR 335: Lambda Expressions for the JavaTM Programming Language
Java 8 新特性概述
Lambda Expressions in Java 8

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/67955.html

相關(guān)文章

  • Python - 閉包Closure

    摘要:恩如期來(lái)啦閉包一函數(shù)作為返回值介紹閉包之前,先了解一下函數(shù)作為返回值的情況。例如之前介紹的裝飾器中,就出現(xiàn)了將函數(shù)作為返回值。當(dāng)執(zhí)行時(shí),相當(dāng)于執(zhí)行,且包含。允許使用關(guān)鍵字創(chuàng)造匿名函數(shù)。例如調(diào)用默認(rèn)可以把匿名函數(shù)作為返回值返回,例如 恩~ 如期來(lái)啦閉包~ 一、函數(shù)作為返回值 介紹閉包之前,先了解一下函數(shù)作為返回值的情況。高階函數(shù)除了可以接收函數(shù)作為參數(shù)外,還可以把函數(shù)作為結(jié)果值返回。...

    Jason_Geng 評(píng)論0 收藏0
  • 閉包

    摘要:閉包在計(jì)算機(jī)科學(xué)中,閉包是詞法閉包的簡(jiǎn)稱,是引用了自由變量的函數(shù)。所以,有另一種說(shuō)法認(rèn)為閉包是由函數(shù)和與其相關(guān)的引用環(huán)境組合而成的實(shí)體。通過(guò)閉包完成了私有的成員和方法的封裝。 閉包 在計(jì)算機(jī)科學(xué)中,閉包(Closure)是詞法閉包(Lexical Closure)的簡(jiǎn)稱,是引用了自由變量的函數(shù)。這個(gè)被引用的自由變量將和這個(gè)函數(shù)一同存在,即使已經(jīng)離開(kāi)了創(chuàng)造它的環(huán)境也不例外。所以,...

    ccj659 評(píng)論0 收藏0
  • Python進(jìn)階細(xì)節(jié)

    摘要:進(jìn)階細(xì)節(jié)根據(jù)慕課網(wǎng)七月老師視頻整理一切皆對(duì)象對(duì)與來(lái)說(shuō),一切皆對(duì)象,包括函數(shù)。閉包的意義在于返回了一個(gè)現(xiàn)場(chǎng),如果沒(méi)有閉包,很容易被外部的變量所影響。重復(fù)定義可見(jiàn)此時(shí)返回了不再是閉包了。注意該方法的返回值只能是布爾類型,即或。 Python進(jìn)階細(xì)節(jié) 根據(jù)慕課網(wǎng)七月老師視頻整理 一切皆對(duì)象 對(duì)與Python來(lái)說(shuō),一切皆對(duì)象,包括函數(shù)。在其他語(yǔ)言比如c++中,函數(shù)只是一段可執(zhí)行的代碼,只要你獲...

    tomato 評(píng)論0 收藏0
  • Java8實(shí)戰(zhàn)》-第三章讀書(shū)筆記Lambda達(dá)式-01)

    摘要:之前,使用匿名類給蘋(píng)果排序的代碼是的,這段代碼看上去并不是那么的清晰明了,使用表達(dá)式改進(jìn)后或者是不得不承認(rèn),代碼看起來(lái)跟清晰了。這是由泛型接口內(nèi)部實(shí)現(xiàn)方式造成的。 # Lambda表達(dá)式在《Java8實(shí)戰(zhàn)》中第三章主要講的是Lambda表達(dá)式,在上一章節(jié)的筆記中我們利用了行為參數(shù)化來(lái)因?qū)Σ粩嘧兓男枨螅詈笪覀円彩褂玫搅薒ambda,通過(guò)表達(dá)式為我們簡(jiǎn)化了很多代碼從而極大地提高了我們的...

    longshengwang 評(píng)論0 收藏0
  • php易錯(cuò)筆記-流程控制,函數(shù)

    摘要:的語(yǔ)法和其它流程控制結(jié)構(gòu)相似部分允許設(shè)定代碼段的行為。返回值在失敗時(shí)返回并且發(fā)出警告。當(dāng)一個(gè)函數(shù)是有條件被定義時(shí),必須在調(diào)用函數(shù)之前定義。有條件的函數(shù)不能在此處調(diào)用函數(shù),因?yàn)樗€不存在,但可以調(diào)用函數(shù)。 流程控制 PHP 提供了一些流程控制的替代語(yǔ)法,包括 if,while,for,foreach 和 switch。替代語(yǔ)法的基本形式是把左花括號(hào)({)換成冒號(hào)(:),把右花括號(hào)(})分...

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

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

0條評(píng)論

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