欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

如何更快樂的使用Java8中的Lambda特性

前言

網(wǎng)站設計、成都做網(wǎng)站的開發(fā),更需要了解用戶,從用戶角度來建設網(wǎng)站,獲得較好的用戶體驗。創(chuàng)新互聯(lián)公司多年互聯(lián)網(wǎng)經(jīng)驗,見的多,溝通容易、能幫助客戶提出的運營建議。作為成都一家網(wǎng)絡公司,打造的就是網(wǎng)站建設產(chǎn)品直銷的概念。選擇創(chuàng)新互聯(lián)公司,不只是建站,我們把建站作為產(chǎn)品,不斷的更新、完善,讓每位來訪用戶感受到浩方產(chǎn)品的價值服務。

Java 8 的 Lambda 特性較之于先前的泛型加入更能鼓舞人心的,我對 Lambda 的理解是它得以讓 Java 以函數(shù)式思維的方式來寫代碼。而寫出的代碼是否是函數(shù)式,并不單純在包含了多少 Lambda 表達式,而在思維,要神似。

實際中看過一些代碼,為了 Lambda 表達式而 Lambda(函數(shù)式),有一種少年不識愁滋味,為賦新詞強說愁的味道。從而致使原本一個簡單的方調(diào)用硬生生的要顯式的用類如 apply(), accept(obj) 等形式。不僅造成代碼可讀性差,且可測試性也變壞了。

為什么說的是快樂的使用 Java 8 的 Lambda 呢?我竊以為第一個念頭聲明 Lambda 表達式為實例/類變量(像本文第一段代碼那樣),而不是方法的,一定會覺得如此使用方式很快樂的。所謂獨樂樂,不如眾樂樂;獨樂樂,眾不樂定然是更大的快樂; 更極致一些,不管什么時候必須是:我快樂,所以你也快樂。

一方面也在于 Java 還沒有進化到 JavaScript 或  Scala 那樣的水平,JavaScript 的函數(shù)類型變量,不一定要用 apply 或 call, 直接括號就能實現(xiàn)方法調(diào)用。Scala 的函數(shù)類型用括號調(diào)用也會自動匹配到 apply 或 update 等方法上去。

看下面的樣本代碼

public class Account {
 
 public BiFunction<String, String, String> fullName = (firstName, lastName) -> {
  //some logic, i.e. logics of fullName in different countries 
  return firstName + " " + lastName;
 };
 
 public String getName() {
  String firstName = "Speaker";
  String lastName = "Wolf";
  return fullName.apply(firstName, lastName);
 }
}

上面的 fullName Lambda 表達式看起來就有點別扭,完全可以寫成一個普通方法

 public String makeFullName(String firstName, String lastName) {
  //return something with logics
 }

那么調(diào)用起來只需要簡單的

makeFullName(firstName, lastName)

那么此例中把簡單方法寫成一個 Lambda 表達式來調(diào)用有什么不友好之處呢?

  • 不利于理解,Lambda 表達式的類型充斥著 Consumer, Function, BiFunction 等太寬泛的聲明
  • 參數(shù)類型與形參分離在表達式等號兩邊,不利于一一對應(右方重復一遍參數(shù)類型更不可取),真正的返回值也不明了
  • 調(diào)用時更得多余的 get(), accept(obj), apply(obj1, obj2) 那樣的方法
  • 既然有邏輯,就應該有測試,Lambda 表達式雖是一個變量也不例如,測試時也不得用 apply 那樣的調(diào)用
  • Lambda 表達式為變量的形式,可能會隨每一個對象實例有一單獨的拷貝。當然聲明為靜態(tài)可以避免。
  • 重構(gòu)時更需大動干戈,比如前面的例子還要考慮 middleName 的情況,表達式要更動為
public TriFunction<String, String, String, String> fullName = (firstName, middleName, lastName) -> {
 //.......
}

JDK 中還沒有 TriFunction, 還得自己創(chuàng)造,不同數(shù)量的參數(shù)都得更新 Lambda 表達式的類型。如果是一個普通方法重構(gòu)起來就方便多了,跟多一個人多一副碗筷一樣。

 解釋上面第 #5 條,對于方法,實現(xiàn)代碼在 JVM 中只有一份,而 Lambda 實例變量如果不捕獲外部變量的話,與方法是一樣的,例如前面的 Account 為例

Account account1 = new Account();
Account account2 = new Account();
System.out.println(account1.fullName == account2.fullName); //true

但是 Lambda 表達式需捕獲外部變量時,例如

private String suffix = "Sir";
public BiFunction<String, String, String> fullName = (firstName, lastName) -> {
 return firstName + " " + lastName + " " + suffix;
};
 
.......
Account account1 = new Account();
Account account2 = new Account();
account1.fullName == account2.fullName; //就是 false 了, 而如果 suffix 是一個靜態(tài)的變量時這個等式又是 true 了

那么新建的兩個 Account 對象的 fullName 屬性就不是同一個了。因為 Lambda 需要捕獲外部一個不確定的值,所以它也隨宿主實例也變。

難道不應該用 Lambda 表達式變量,那倒不是,如果一個方法接受的是一個函數(shù),如

public String getName(BiFunction<String, String, String> builder) {
 return builder.apply(firstName, lastName);
}

那么是可以聲明一個 Lambda 表達式變量,來傳入。不過這種情況下用方法引用還是更方便些,方法的測試總是比 Lambda 表達式的測試容易。

String name = getName(this::makeFullName);

個人習慣,一般需要 Lambda 表達式變量時基本是聲明為局部變量,或是調(diào)用接受函數(shù)參數(shù)的方法時以內(nèi)聯(lián)的方法書寫,像

String name = getName((firstName, lastName) -> {
 //logics
 return ......
});

對于使用方法引用方式的重構(gòu)也不難,getName() 的參數(shù)類型變?yōu)?TriFunction, makeFullName() 方法再加一個參數(shù)就行, 調(diào)用形式仍然不變,還是

String name = getName(this::makeFullName);

如果引用的方法是別人寫的也不用慌,無須總?cè)?chuàng)建一樣的方法簽名來強型上方法引用,也可以和改 Lambda 實現(xiàn)代碼一樣的方式比改動,如下

String name = getName((firstName, lastName) -> 
 makeFullName(firstName, lastName) + " " + suffix
)

本人希望的是,對函數(shù)的 apply(), accept(obj) 這樣的顯式調(diào)用應該是框架設計實現(xiàn)的職責,對框架使用者應該透明,或者說是隱藏背后的細節(jié),只管傳入需要的函數(shù)類型或方法引用。如果函數(shù)實現(xiàn)需要共享的話,寫成方法更優(yōu)于一個 Lambda 表達式,方法容易單獨測試。特別是用 Mockito 捕獲到了一個傳入某個方法的 Lambda  表達式實例時,不那么好驗證它的內(nèi)部實現(xiàn)。

小結(jié)一下:

  • 函數(shù)式思維最關(guān)鍵應該是 Data In, Data Out, 編程語言 Lambda 特性可以促使我們達成這一目的; 但不是代碼中有了  Lambda 表達就是函數(shù)式風格。
  • 其次代碼的首先是人閱讀,其次才是機器,所以它應該表達直截,明了,很強的可讀性與可測試性。
  • 具體講如何快樂使用 Java 8 的 Lambda 呢,僅代表本人想法,可以用內(nèi)聯(lián)式,或方法引用,或局部的 Lambda 表達式變量,最后才是實例/類的 Lambda 表達式變量。

補充一個例子,在方法體中重復聲明完全相同的不捕獲任何外部變量的 Lambda 表達式都是新的實例

 Consumer<String> f1 = a -> System.out.println(a);
 Consumer<String> f2 = a -> System.out.println(a);
 System.out.println(f1 == f2); //false

以上測試在 Java 8 平臺上進行的。

lambda表達式優(yōu)劣

lambda表達式有優(yōu)點也有缺點,優(yōu)點在于大大簡化代碼行數(shù),使代碼在一定程度上變的簡潔干凈,但是同樣的,這可能也會是一個缺點,由于省略了太多東西,代碼可讀性有可能在一定程度上會降低,這個完全取決于你使用lambda表達式的位置所設計的API是否被你的代碼的其他閱讀者所熟悉。另外的優(yōu)點,也是lambda表達式比較顯眼的優(yōu)點就是對外部定義的局部變量的使用更加靈活,想象一種極端情況,你的代碼中有地方需要接口回調(diào)套接口回調(diào),有可能套了好幾層,雖然這種情況出現(xiàn)的概率比較低,但是一旦出現(xiàn)這種代碼,lambda表達式的這個優(yōu)點就到了大顯身手的時機。雖然我說了,lambda表達式能用的地方非常有限,但是不得不否認,接口中只有一個抽象方法這種情況在接口回調(diào)中發(fā)生的概率絕對比接口中有多個抽象方法的概率高的多,所以,雖然使用情況很單一,但是能用到的次數(shù)卻足夠的多,如果你決定用lambda表達式替換你項目中接口回調(diào)的傳統(tǒng)寫法,你會發(fā)現(xiàn),這樣的情況非常多。

總而言之,接口回調(diào)和lambda表達式這兩種寫法各有優(yōu)劣,java 8在出現(xiàn)lambda表達式以后不代表原先的寫法不能再用了,所以如何選擇適合項目的寫法,全看各位開發(fā)者如何自己選擇,現(xiàn)在多了一種寫法可選,總歸是一件好事。

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對創(chuàng)新互聯(lián)的支持。

網(wǎng)站題目:如何更快樂的使用Java8中的Lambda特性
網(wǎng)址分享:http://chinadenli.net/article4/gesjoe.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供靜態(tài)網(wǎng)站App開發(fā)自適應網(wǎng)站網(wǎng)站設計網(wǎng)站內(nèi)鏈

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

網(wǎng)站優(yōu)化排名