一、概括Java8新特性
永久區(qū)(堆內(nèi)存的永久帶)變成了元空間MetaSpace(物理內(nèi)存,更快,存放class字節(jié)碼對(duì)象)
設(shè)置元空間大小的方式 MetaSpaceSize/MaxMetaSpaceSize
新日期工具類
Lambda表達(dá)式
MethodRef方法引用
StreamAPI
Optional容器(最大化減少空指針異常)
Interface新特性(默認(rèn)方法和靜態(tài)方法)
二、淺談編程語(yǔ)言發(fā)展歷史
談函數(shù)式編程之前,我們聊一聊編程語(yǔ)言發(fā)展歷史。
1.面向機(jī)器編程
我們用硬件上的電壓高低來(lái)描述0和1,從而機(jī)器可以來(lái)存儲(chǔ)二進(jìn)制數(shù)據(jù)。
再利用電路中的與門,非門,或門,或非門等等等來(lái)處理電壓高低這兩種狀態(tài),
再結(jié)合數(shù)學(xué)中的二進(jìn)制與之匹配,總結(jié)出一套規(guī)律,從而就完成機(jī)器對(duì)二進(jìn)制的運(yùn)算。
計(jì)算機(jī)沒有數(shù)學(xué)運(yùn)算,只有加法運(yùn)算,我們的加減乘除都是通過位與,位或,位非等方式進(jìn)行二進(jìn)制計(jì)算得到的結(jié)果。
計(jì)算機(jī)有了存儲(chǔ)和處理二進(jìn)制數(shù)據(jù)的功能之后,新世界來(lái)臨了,二進(jìn)制機(jī)器語(yǔ)言誕生了。
二進(jìn)制通過數(shù)學(xué)轉(zhuǎn)換得到了十進(jìn)制,二進(jìn)制通過碼表得到了文字,二進(jìn)制通過像素信息得到了圖片等等。
但二進(jìn)制不符合人類邏輯,所以匯編語(yǔ)言誕生了,匯編語(yǔ)言的單詞類似與碼表一樣映射成一個(gè)個(gè)二進(jìn)制指令去操作機(jī)器進(jìn)行數(shù)據(jù)處理。
匯編語(yǔ)言把數(shù)據(jù)往內(nèi)存中進(jìn)棧,壓棧,cpu累加寄存器運(yùn)算等等一系列操作,完成了我們對(duì)數(shù)據(jù)處理的要求。
匯編語(yǔ)言直接指令電子元器件處理數(shù)據(jù),所以匯編語(yǔ)言不能稱之為語(yǔ)言,叫做匯編指令更加適合,因?yàn)樗褪嵌M(jìn)制指令的映射。
這也是硬件驅(qū)動(dòng)大部分是用匯編指令編程的原因所在(也有很多是匯編和C來(lái)混編驅(qū)動(dòng)程序)。
2.面向過程編程
匯編指令編程也不符合我們?nèi)祟惖倪壿?,而是我們?duì)二進(jìn)制語(yǔ)言的一種妥協(xié)。
既然匯編語(yǔ)言可以映射成二進(jìn)制指令,那么二進(jìn)制指令也就可以映射成符合人類邏輯的指令語(yǔ)言,C語(yǔ)言誕生了!
C語(yǔ)言有條件判斷,循環(huán)語(yǔ)句,函數(shù)處理,數(shù)據(jù)類型等等一系列高級(jí)操作,完全符合了人類對(duì)數(shù)據(jù)處理的要求。
但是C語(yǔ)言是面向過程的,注重其實(shí)現(xiàn)的過程,它更多注重的是對(duì)數(shù)據(jù)的封裝,而非功能模塊的封裝。
比如說結(jié)構(gòu)體,共用體等等,都是對(duì)各種數(shù)據(jù)類型的組合封裝和復(fù)用。
這就讓我們?cè)谑褂盟臅r(shí)候,不得不面向過程,直接操作指針也讓我們編寫難度加大。
本人不是C語(yǔ)言開發(fā)者,不再過多描述。
3.面向?qū)ο缶幊?C++優(yōu)化了C語(yǔ)言,開始轉(zhuǎn)向面向?qū)ο缶幊?,但也包含面向過程編程的部分,C指針讓我們?cè)趦?nèi)存中操作數(shù)據(jù)更加高效,但也更難維護(hù)。
Java優(yōu)化了C++,把指針隱藏了起來(lái),用引用來(lái)代替指針操作數(shù)據(jù),加入垃圾對(duì)象回收機(jī)制,讓編寫代碼和維護(hù)代碼變得更加容易。
舉個(gè)例子,C語(yǔ)言中操作數(shù)組直接是數(shù)組的首地址,而Java操作數(shù)組則是引用類型變量指向數(shù)組首地址。
當(dāng)引用變量指向數(shù)組對(duì)象的引用鏈斷開,又沒有其他引用變量指向該數(shù)組對(duì)象時(shí),這個(gè)數(shù)組對(duì)象會(huì)變成垃圾對(duì)象,GC定時(shí)回收,無(wú)需再關(guān)心它的內(nèi)存釋放。
眾所周知,Java是面向?qū)ο笳Z(yǔ)言。封裝,繼承,多態(tài),抽象等一系列高級(jí)特性來(lái)完善它的面向?qū)ο蟆?而我們用的最多的方式,就是去創(chuàng)建類類型來(lái)描述對(duì)象,用數(shù)據(jù)映射對(duì)象屬性,用函數(shù)映射對(duì)象行為,根據(jù)類類型規(guī)范創(chuàng)建對(duì)象,根據(jù)接口規(guī)范來(lái)約束行為等等等
4.面向函數(shù)式編程
但是面向?qū)ο笠灿斜锥?,比如說我只是想用一個(gè)簡(jiǎn)單函數(shù)而已,你卻想讓我把函數(shù)變成行為,再指向某個(gè)對(duì)象中去,把函數(shù)先類屬于某個(gè)對(duì)象,再去用對(duì)象調(diào)用它。
當(dāng)然Java也有改進(jìn)這一方面的東西,比如匿名內(nèi)部類可以很好完成這一要求,但是還不夠簡(jiǎn)潔!
所以Java8函數(shù)式編程來(lái)了,你不用關(guān)心怎么去實(shí)現(xiàn)(How),只關(guān)心你要做什么就行了(What)
三、下面我們來(lái)看一個(gè)簡(jiǎn)單的例子:
public class LambdaDemo {
public int[] arr;
@Before
public void resource(){
arr = new int[]{10,20,30,40};
}
//傳統(tǒng)方式 定義求和函數(shù)
public int sum(int[] arr){
int sum = 0;
for (int i = 0; i < arr.length; i++) {
sum += arr[i];
}
return sum;
}
@Test
public void test(){
//1. 傳統(tǒng)方式
int result1 = sum(arr); //調(diào)用函數(shù)
System.out.println(result1); //100
//2. Lambda方式 定義求和函數(shù)
//Function<>此處第二個(gè)泛型不能是int
Function<int[],Integer> result = (arr) -> {
int sum = 0;
for (int i = 0; i < arr.length; i++) {
sum += arr[i];
}
return sum;
};
int result2 = result.apply(arr); //調(diào)用函數(shù)
System.out.println(result2); //100
//3. Lambda+Stream方式 定義求和函數(shù)
//Function<>此處第二個(gè)泛型不能是int
Function<int[],Integer> sum = (arr) -> Arrays.stream(arr).reduce(0,Integer::sum);
Integer result3 = sum.apply(arr); //調(diào)用函數(shù)
System.out.println(result3); //100
}
}
四、分析Lambda表達(dá)式
原先我們?cè)贏函數(shù)內(nèi)使用另外一個(gè)B函數(shù),需要在A函數(shù)外部定義這個(gè)B函數(shù),最后在A函數(shù)內(nèi)部完成調(diào)用。
在Java8中我們發(fā)現(xiàn),函數(shù)式編程讓函數(shù)的使用更加簡(jiǎn)單靈活。
我們用一個(gè)函數(shù)式接口類型變量去接收符合這個(gè)接口的行為規(guī)范的方法(也就是Lambda方法體)。
Function<int[],Integer> sum = (arr) -> Arrays.stream(arr).reduce(0,Integer::sum);
就可以使用函數(shù)式接口抽象方法去調(diào)用這個(gè)函數(shù)。
Integer result3 = sum.apply(arr);
原先我們求和方法要寫了7行代碼,現(xiàn)在用Lambda+StreamAPI只要寫1行代碼??!
我們常見的行為向上抽取為函數(shù)式接口,這種新接口數(shù)據(jù)類型接收了我們的函數(shù)。
從此我們函數(shù)定義可以像int a = 10;這樣簡(jiǎn)單。
而使用函數(shù)直接用a.abstractmethod()調(diào)用抽象方法即可。
五、函數(shù)式編程才是Java8的秘密?。?!
再回過頭來(lái)總結(jié)Java8新特性:
Lambda表達(dá)式
MethodRef方法引用
StreamAPI
Optional容器(最大化減少空指針異常)
Interface新特性(默認(rèn)方法和靜態(tài)方法)
我們發(fā)現(xiàn):
1.StreamAPI很多方法返回的是Optional容器類對(duì)象,從而來(lái)避免空指針異常,
另外在optional的map()函數(shù)中使用它包裹的對(duì)象的方法變得更加安全。
可以說Optional容器一定程度上為StreamAPI服務(wù)。
當(dāng)然我們也可以單獨(dú)使用它,畢竟map()函數(shù)還是很方便的。
2.MethodRef方法引用可以被函數(shù)式接口類型變量接收,也可以高效復(fù)用函數(shù)!
3.Lambda表達(dá)式通過函數(shù)式接口類型變量來(lái)定義,很大程度上代替了原先的函數(shù)定義!
4.集合和數(shù)組通過StreamAPI的流模型來(lái)完成各種遍歷、過濾、分組、元素運(yùn)算等操作,
又很大程度上代替了for循環(huán),while循環(huán)和迭代器!
5.我們?cè)偃ズ瘮?shù)式接口里面看看,發(fā)現(xiàn)有很多默認(rèn)方法和靜態(tài)方法!
這不正是Java8的Interface新特性嗎?
Interface新特性一定程度上破壞了原有接口的特性,它最大的作用原來(lái)是為了函數(shù)式接口!
提供的一系列默認(rèn)方法和靜態(tài)方法的參數(shù)又去接收新的函數(shù)式接口類型數(shù)據(jù)
這些默認(rèn)方法和靜態(tài)方法返回值類型又是本函數(shù)式接口類型。
我們有Lambda方法體和MethodRef方法引用做值,又可以像StreamAPI那樣鏈?zhǔn)骄幊獭? 無(wú)比高效的編程方式,write less , do more
原來(lái)Java8幾乎所有的新特性都在為一個(gè)東西服務(wù):函數(shù)式編程?。?!
函數(shù)式編程,這才是Java8的秘密。
六、大勢(shì)所趨:多范式編程
我們發(fā)現(xiàn)了Java8的秘密武器:函數(shù)式編程!
但是面向?qū)ο缶幊桃彩蔷幊讨蟹浅?yōu)秀的范式,我們并沒有拋棄它,而是搭配使用。
這就是多范式編程,根據(jù)每個(gè)人不同的喜好和習(xí)慣去編寫代碼,也是眾多編程語(yǔ)言發(fā)展的趨勢(shì),你值得擁有!
畢竟大家好才是真的好!
純屬個(gè)人見解,歡迎私信討論
最后編輯于 :2020.10.25 01:31:12
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者 【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。 平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。