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

資訊專欄INFORMATION COLUMN

Java 8的Lambda及其在Android 開發(fā)中的應(yīng)用

liuhh / 1933人閱讀

摘要:由此可以看出,使用可以讓你的代碼在某些情況下達(dá)到何等的簡(jiǎn)潔。如果沒(méi)有參數(shù),那么前面的是必須存在的。我們知道中的,而其實(shí)就是一個(gè)只定義了一個(gè)抽象方法的。也就是說(shuō),可以訪問(wèn)定義它的那個(gè)方法的局部變量。而在里面,還可以訪問(wèn)所謂的局部變量。

上次在盆友圈發(fā)了一張照片

上面的兩段代碼是完全等效的,但是代碼行數(shù)從11行降低到了一行,更不用說(shuō)在第一段代碼里面,我在run方法的前后以及內(nèi)部都沒(méi)有加入任何的空行。由此可以看出,使用lambda可以讓你的Java代碼在某些情況下達(dá)到何等的簡(jiǎn)潔。
那么問(wèn)題來(lái)了。。。

什么叫l(wèi)ambda呢?

Java 8 給我們帶來(lái)了lambda,然而在Oracle的文檔中,我沒(méi)有找到lambda的定義,wikipedia里面也沒(méi)有找到適合Java中的lambda的定義。寫這篇文章的時(shí)候,我在這里 看到一篇很好的介紹lambda的文章,它里面給了一個(gè)定義,我覺(jué)得還挺合適的。

A lambda expression is a block of code with parameters.

lambda的寫法

首先列舉一個(gè)完整的lambda expression:

(int a, int b) -> {
    System.out.println("Performing add operation...");
    return a+b;
}

一個(gè)lambda expression由三部分組成:

參數(shù):(int a, int b)是這個(gè)lambda expression的參數(shù)部分,包括參數(shù)類型和參數(shù)名

箭頭:->

代碼塊:就是用"{}"包含著的那兩句代碼。

上面說(shuō)的是一個(gè)完整的lambda表達(dá)式,在很多情況下,很多東西是可以省略的。比如說(shuō),當(dāng)系統(tǒng)可以根據(jù)上下文自動(dòng)推斷出參數(shù)的類型的時(shí)候,參數(shù)類型是可以省略的。這樣的話就可以寫成:

(a, b) -> {
    System.out.println("Performing add operation...");
    return a+b;
}

系統(tǒng)怎么自動(dòng)推斷出參數(shù)類型的呢?這個(gè)在下面我們就可以看到。
再比如,如果只有一個(gè)參數(shù),而參數(shù)的類型又可以自動(dòng)判斷,那么連()也是可以省略的,那么就寫成了:

a -> {
    System.out.println("Performing add operation...");
    return a+a;
}

再再比如,如果代碼塊里面只有一行代碼,那么{}也是可以省略的,那么就寫成了:

a ->
    return a+a;

是的,可以寫在同一行

a -> return a+a;

讓我們更進(jìn)一步,在這里,return其實(shí)也是沒(méi)必要的。

a -> a+a;

Great, 如果沒(méi)有參數(shù)的話,是不是就可以寫成:

-> a+a

呢?
很可惜,答案是否定的。如果沒(méi)有參數(shù),那么前面的()是必須存在的。也就是說(shuō),必須寫成:

()-> a+a
lambda的用法

實(shí)際上,如果你直接把上面的代碼放到你的編輯器里面,你的IDE是會(huì)報(bào)錯(cuò)的,因?yàn)閘ambda是不能這樣使用的。lambda的使用永遠(yuǎn)要跟一個(gè)叫做Functional Interface的東西綁定在一起。什么叫Functional Interface呢?Functional Interface也是Java8 中引入的概念.是的,是為了lambda。我們知道java中的interface,而Functional Interface其實(shí)就是一個(gè)只定義了一個(gè)抽象方法interface。比如Runnable 這個(gè)interface就只有一個(gè)run方法,那么它就是一個(gè)Functional Interface。
如果你對(duì)“重復(fù)”這件事情比較敏感的話,你可能又有疑問(wèn)了,什么叫只定義了一個(gè)抽象方法的interface?interface中的方法不都是抽象的嗎?你這個(gè)是病句吧,重復(fù)了。。。Well,在java8以前是這樣的,然而在java8中,Java引進(jìn)了default method的概念,說(shuō)白了就是帶有具體實(shí)現(xiàn)的方法:

public interface DuckInterface {
    public void wwwalksLikeADuck();
    public default void tttalksLikeADuck() {
        System.out.println("Quack!");
    }
}

在上面的例子中,tttalksLikeADuck()就是一個(gè)default method,注意到這個(gè)方法的定義中有一個(gè)“default”修飾符。相信很多人會(huì)覺(jué)得這是個(gè)非常有用的feature,我也是這樣覺(jué)得的。
再說(shuō)回Functional Interfacel和lambda。剛剛說(shuō)到,lambda必須和Functional Interface配套使用,那怎么配套使用呢?
以安卓里面的View.OnClickListener為例(它也是個(gè)Functional Interface)如果沒(méi)有l(wèi)ambda,我們經(jīng)常會(huì)這樣使用的。

View.OnClickListener onClickListener = new View.OnClickListener() {    
    @Override
    public void onClick(View view) {
        handleClick();
    }
});
findViewById(R.id.someView).setOnClickListener(onClickListener);

或者直接使用匿名內(nèi)部類:

findViewById(R.id.someView).setOnClickListener(new View.OnClickListener() {    
    @Override
    public void onClick(View view) {
        handleClick();
    }
});

在上面的5行代碼中,有用的其實(shí)只有handleClick(),而我們卻必須用5行代碼去處理,這是非常繁瑣的。在Java 8以前的世界,這樣的代碼非常多。有一個(gè)專門的名詞來(lái)稱呼這種性質(zhì)的代碼,叫“boilerplate code”,我不知到中文叫什么。。。
現(xiàn)在好了,有了lambda,我們可以這樣寫:

View.OnClickListener onClickListener = view -> handleClick();
findViewById(R.id.someView).setOnClickListener(onClickListener);

匿名內(nèi)部類的版本:

findViewById(R.id.someView).setOnClickListener(view -> handleClick());

是不是瞬間覺(jué)得簡(jiǎn)潔優(yōu)雅了?
從上面的例子可以看到,lambda其實(shí)就相當(dāng)于簡(jiǎn)化了Functional Interface的實(shí)例的創(chuàng)建。當(dāng)然,從真正意義上來(lái)講,lambda的意義不止這么一點(diǎn)點(diǎn),只不過(guò)從使用的角度來(lái)看,你可以這樣看待。

從lambda到Functional Programming

這里稍微討論一下關(guān)于lambda的其他一些特性。
在上面的例子中

View.OnClickListener onClickListener = view -> handleClick();
findViewById(R.id.someView).setOnClickListener(onClickListener);

這里,你既可以吧onClickListener看作是OnClickListener的一個(gè)instance,也可以把它看做一個(gè)代碼塊,后面的那句findViewById(R.id.someView).setOnClickListener(onClickListener);就相當(dāng)于是吧這個(gè)代碼塊傳給了view.setOnClickListener()這個(gè)函數(shù)。也就是說(shuō),從某種意義上來(lái)講,你可以把lambda看作是可以相互傳遞的代碼塊。而傳遞代碼塊,是Functional Programming(一下簡(jiǎn)稱FP)非常重要的一個(gè)特征,雖然說(shuō)這兩者其實(shí)沒(méi)有什么對(duì)等關(guān)系。因?yàn)镕P的本質(zhì)特征是,運(yùn)行一段代碼并不會(huì)改變事物的狀態(tài),也就是說(shuō),沒(méi)有side-effect。而lambda里面是可以調(diào)用所在的類的成員方法的、也可以訪問(wèn)和修改所在類的成員變量的。
話說(shuō)回來(lái),關(guān)于FP我也不是了解的很多,我本身并沒(méi)有多少FP的經(jīng)驗(yàn),雖然對(duì)Ruby有一定了解,但Ruby也只是“可以比較好的進(jìn)行”FP而已,也不是純粹的FP語(yǔ)言。純粹的FP語(yǔ)言是List(包括Scheme,Clojure)、Haskell、ML等等這些。關(guān)于FP,Robert Martin(就是《Clean code》和《The Clean Coder》的作者)有一個(gè)講得很好的視頻在這里。
剛剛講到,lambda的代碼塊可以訪問(wèn)所在類的成員變量和成員方法,那對(duì)于局部變量?
我們知道,方法內(nèi)部定義的匿名類是可以訪問(wèn)所在方法的final局部變量的,作為Functional Interface的簡(jiǎn)寫方式,lambda在這點(diǎn)上面跟匿名類保持了一致。也就是說(shuō),lambda可以訪問(wèn)定義它的那個(gè)方法的final局部變量。而在Java8里面,lambda還可以訪問(wèn)所謂“Effectively final”的局部變量。所謂“Effectively final”的局部變量,就是說(shuō)除了在定義的時(shí)候給了一個(gè)初始值以為,在沒(méi)有改變過(guò)她的值的那些局部變量:

int age = 26;    //在這里,age就是Effectively final的局部變量
Runnable r = () -> System.out.println("My age is "+age);
new Thread(r).start();
在Android開發(fā)中的應(yīng)用

可是!?。ndroid只支持Java 7???怎么辦?莫急,要相信網(wǎng)友的力量,已經(jīng)有人開發(fā)了gradle的插件,可以將java 8中的labmda表達(dá)式在編譯出來(lái)的bytecode里面,給它轉(zhuǎn)化成Java 7兼容的代碼。猛戳這里,使用方法那個(gè)頁(yè)面都用,在這里就不贅述了。

如果對(duì)文章有任何意見(jiàn)或建議,或者是發(fā)現(xiàn)文中有任何問(wèn)題歡迎留言!

作者 小創(chuàng) 更多文章 | Github | 公眾號(hào)

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

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

相關(guān)文章

  • kotlin學(xué)習(xí)筆記-異常好玩list集合總結(jié)

    摘要:可能是最流行的集合類型。它是一個(gè)范性有序的集合。一個(gè)無(wú)序并不支持重復(fù)的集合。接口繼承接口,集合中可以存放重復(fù)對(duì)象。集合類提供了,等高階函數(shù)去處理。我們聲明一個(gè)集合或者數(shù)組,可以轉(zhuǎn)換成相應(yīng)類型的集合。調(diào)用轉(zhuǎn)換為可變集合。 不積跬步無(wú)以至千里,不積小流無(wú)以成江海 先看看Kotlin中for循環(huán)的遍歷 fun testList(){ var StringVal = 12_...

    RebeccaZhong 評(píng)論0 收藏0
  • Android項(xiàng)目中使用Java8

    摘要:現(xiàn)在爸爸終于讓平臺(tái)支持了,這篇文章中便來(lái)和大家聊聊如何在項(xiàng)目中配置使用。要想在項(xiàng)目中使用的新特性,需要將你的升級(jí)到及以上版本,并采用新的編譯。 轉(zhuǎn)載請(qǐng)注明出處:https://zhuanlan.zhihu.com/p/23279894 前言 在過(guò)去的文章中我介紹過(guò)Java8的一些新特性,包括: Java8新特性第1章(Lambda表達(dá)式) Java8新特性第2章(接口默認(rèn)方法) J...

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

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

0條評(píng)論

liuhh

|高級(jí)講師

TA的文章

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