Java中的类型推断和lambda表达式
文章目錄
- 簡介
- 類型的顯示使用
- Stream中的類型推斷
- 類型推斷中變量名字的重要性
- 類型推斷對(duì)性能的影響
- 類型推斷的限制
- 總結(jié)
簡介
java是強(qiáng)類型的編程語言,每個(gè)java中使用到的變量都需要定義它的類型,否則會(huì)編譯失敗。強(qiáng)類型語言的好處就是可以盡可能的在編譯期間就發(fā)現(xiàn)代碼中可能出現(xiàn)的問題,從而減少在運(yùn)行時(shí)出現(xiàn)問題的可能性。
相對(duì)的,強(qiáng)類型語言的缺點(diǎn)就是不那么的靈活多變,寫起來比較冗余。
JDK8之前,java是不支持類型推斷的,在JDK8中,引入了lambda表達(dá)式,從此類型推斷產(chǎn)生了。
本文將會(huì)講解類型推斷在lambda表達(dá)式中的最佳實(shí)踐和在使用中應(yīng)該注意的事項(xiàng)。
更多精彩內(nèi)容且看:
- 區(qū)塊鏈從入門到放棄系列教程-涵蓋密碼學(xué),超級(jí)賬本,以太坊,Libra,比特幣等持續(xù)更新
- Spring Boot 2.X系列教程:七天從無到有掌握Spring Boot-持續(xù)更新
- Spring 5.X系列教程:滿足你對(duì)Spring5的一切想象-持續(xù)更新
- java程序員從小工到專家成神之路(2020版)-持續(xù)更新中,附詳細(xì)文章教程
更多內(nèi)容請(qǐng)?jiān)L問www.flydean.com
類型的顯示使用
假如我們定義了一個(gè)CustUser類,并且其中有age和name兩個(gè)屬性:
@Data @AllArgsConstructor public class CustUser {int age;String name; }看下我們?cè)趺丛赟tream中顯示使用類型:
public static void testStream(){Stream.of(new CustUser(10,"alice"), new CustUser(20,"bluce")).forEach( (CustUser custUser)-> System.out.println(custUser.name));}上面的例子中,我們構(gòu)建了一個(gè)CustUser類型的Stream,并在forEach方法中對(duì)CustUser進(jìn)行處理。
forEach接收一個(gè)Consumer對(duì)象,Consumer需要實(shí)現(xiàn)void accept(T t)方法。因?yàn)镃onsumer函數(shù)接口,我們可以使用lambda表達(dá)式來替換。
這里,我們顯示傳入一個(gè)CustUser類型。代碼編譯是沒有問題的,但是看起來復(fù)雜了點(diǎn)。接下來我們看下怎么在Stream中使用類型推斷。
Stream中的類型推斷
上面的例子,我們可以改寫成這樣:
public static void testInference(){Stream.of(new CustUser(10,"alice"), new CustUser(20,"bluce")).forEach(custUser-> System.out.println(custUser.name));}這里我們并沒有定義custUser的類型,但是java可以從Stream中的類型推斷出來。所以這樣寫是沒有問題的,可以正常通過編譯。
類型推斷中變量名字的重要性
上面的例子中,我們將變量的名字定義為custUser,查看代碼的人一眼就可以看出來這個(gè)參數(shù)表示的是CustUser類型的custUser參數(shù)。
名字寫的有意義可以很大程度上提升代碼的可讀性和可維護(hù)性。如果你這樣寫:
forEach(u-> System.out.println(u.name)雖然代碼變得更短了,但是失去了可讀的意義,一眼看過去,大家并不知道你這個(gè)u代表的是什么,從而影響了代碼的可讀性。
所以變量名的定義一定要有意義。
類型推斷對(duì)性能的影響
類型推斷是個(gè)好東西,那么有同學(xué)會(huì)問了,類型推斷對(duì)于java的性能會(huì)有影響嗎?
我們可以把java分成編譯和運(yùn)行兩部分。類型推斷是在編譯期間做的事情,可能使用類型推斷會(huì)延長代碼編譯的時(shí)間,但是對(duì)運(yùn)行時(shí)的效率是沒有影響的。
一般來說,我們關(guān)注程序的性能問題是在運(yùn)行時(shí)而不是編譯時(shí),所以類型推斷對(duì)性能是沒有影響的。
類型推斷的限制
java雖然有類型推斷,但是這個(gè)推斷是有一定的限制的,它并不能夠像人一樣去思考,但是也已經(jīng)足夠智能了。下面我們舉個(gè)例子:
public static Comparator<CustUser> createUser1(){return (CustUser user1, CustUser user2) -> user1.getAge() - user2.getAge();}上面的例子中,我們需要?jiǎng)?chuàng)建一個(gè)Comparator,使用lambda表達(dá)式我們可以生成一個(gè)Comparator。
Comparator需要實(shí)現(xiàn)方法int compare(T o1, T o2),傳入兩個(gè)參數(shù),返回一個(gè)int。
上面例子中,我們顯示指定了兩個(gè)參數(shù)的類型是CustUser,編譯沒有問題。
如果不顯示指定CustUser類型可以嗎?
public static Comparator<CustUser> createUser2(){return (user1, user2) -> user1.getAge() - user2.getAge();}答案也是可以的。這個(gè)例子中,我們并沒有傳入user1,user2,java是怎么找到user1和user2的類型呢?
注意,上面的例子中,我們定義了返回類型是CustUser的,Java通過這個(gè)返回類型來推斷出傳入的實(shí)際類型就是CustUser的。是不是很智能。
如果我們將上面的return語句拆分成兩條,會(huì)出現(xiàn)問題問題呢?
Comparator comparator=(user1, user2) -> user1.getAge() - user2.getAge();這時(shí)候就會(huì)編譯報(bào)錯(cuò),說找不到getAge方法。這是因?yàn)槲覀兎祷氐腃omparator并沒有指明類型,所以默認(rèn)情況下是Object類型。Object類型并沒有g(shù)etAge方法,所以報(bào)錯(cuò)。
我們可以這樣改寫:
Comparator<CustUser> comparator=(user1, user2) -> user1.getAge() - user2.getAge();編譯完成,沒有錯(cuò)誤。
總結(jié)
除了JDK8中引入的lambda表示中使用了類型推斷,其實(shí)JDK10中的var本地變量類型也是用到了類型推斷,詳請(qǐng)參考JDK10的新特性:本地變量類型var。
本文的例子https://github.com/ddean2009/
learn-java-base-9-to-20
本文作者:flydean程序那些事
本文鏈接:http://www.flydean.com/java-type-inference-lambda/
本文來源:flydean的博客
歡迎關(guān)注我的公眾號(hào):程序那些事,更多精彩等著您!
總結(jié)
以上是生活随笔為你收集整理的Java中的类型推断和lambda表达式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 小师妹学JavaIO之:文件写入那些事
- 下一篇: 使用site-maven-plugin在