亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

詳解Java?缺失的特性擴(kuò)展方法

 更新時(shí)間:2023年03月27日 15:00:50   作者:周密(之葉)?阿里  
這篇文章主要為大家介紹了Java?缺失的特性擴(kuò)展方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

什么是擴(kuò)展方法

擴(kuò)展方法,就是能夠向現(xiàn)有類型直接“添加”方法,而無(wú)需創(chuàng)建新的派生類型、重新編譯或以其他方式修改現(xiàn)有類型。調(diào)用擴(kuò)展方法的時(shí)候,與調(diào)用在類型中實(shí)際定義的方法相比沒(méi)有明顯的差異。

為什么需要擴(kuò)展方法

考慮要實(shí)現(xiàn)這樣的功能:從 Redis 取出包含多個(gè)商品ID的字符串后(每個(gè)商品ID使用英文逗號(hào)分隔),先對(duì)商品ID進(jìn)行去重(并能夠維持元素的順序),最后再使用英文逗號(hào)將各個(gè)商品ID進(jìn)行連接。

傳統(tǒng)寫(xiě)法:

使用 Stream 寫(xiě)法:

假設(shè)在 Java 中能實(shí)現(xiàn)擴(kuò)展方法,并且我們?yōu)閿?shù)組添加了擴(kuò)展方法 toList(將數(shù)組變?yōu)?nbsp;List),為 List 添加了擴(kuò)展方法 toSet(將 List 變?yōu)?nbsp;LinkedHashSet),為 Collection 添加了擴(kuò)展方法 join(將集合中元素的字符串形式使用給定的連接符進(jìn)行連接),那我們將可以這樣寫(xiě)代碼:

相信此刻你已經(jīng)有了為什么需要擴(kuò)展方法的答案:

可以對(duì)現(xiàn)有的類庫(kù),進(jìn)行直接增強(qiáng),而不是使用工具類

相比使用工具類,使用類型本身的方法寫(xiě)代碼更流暢更舒適

代碼更容易閱讀,因?yàn)槭擎準(zhǔn)秸{(diào)用,而不是用靜態(tài)方法套娃

在 Java 中怎么實(shí)現(xiàn)擴(kuò)展方法

我們先來(lái)問(wèn)問(wèn)最近大火的 ChatGPT:

好吧,ChatGPT 認(rèn)為 Java 里面的擴(kuò)展方法就是通過(guò)工具類提供的靜態(tài)方法 :)。所以接下來(lái)我將介紹一種全新的黑科技:

Manifold(https://github.com/manifold-systems/manifold)

準(zhǔn)備條件

Manifold 的原理和 Lombok 是類似的,也是在編譯期間通過(guò)注解處理器進(jìn)行處理。所以要在 IDEA 中正確使用 Manifold,需要安裝 Manifold IDEA 的插件:

然后再在項(xiàng)目 pom 的 maven-compiler-plugin 中加入 annotationProcessorPaths:

如果你的項(xiàng)目中使用了 Lombok,需要把 Lombok 也加入 annotationProcessorPaths:

編寫(xiě)擴(kuò)展方法

JDK 中,String 的 split 方法,使用的是字符串作為參數(shù),即 String[] split(String)。我們現(xiàn)在來(lái)為 String 添加一個(gè)擴(kuò)展方法 String[] split(char):按給定的字符進(jìn)行分割。

基于 Manifold,編寫(xiě)擴(kuò)展方法:

可以發(fā)現(xiàn)本質(zhì)上還是工具類的靜態(tài)方法,但是有一些要求:

工具類需要使用 Manifold 的 @Extension 注解

靜態(tài)方法中,目標(biāo)類型的參數(shù),需要使用 @This 注解

工具類所在的包名,需要以 extensions.目標(biāo)類型全限定類名 結(jié)尾

—— 用過(guò) C# 的同學(xué)應(yīng)該會(huì)會(huì)心一笑,這就是模仿的 C# 的擴(kuò)展方法。

關(guān)于第 3 點(diǎn),之所以有這個(gè)要求,是因?yàn)?Manifold 希望能快速找到項(xiàng)目中的擴(kuò)展方法,避免對(duì)項(xiàng)目中所有的類進(jìn)行注解掃描,提升處理的效率。

具備了擴(kuò)展方法的能力,現(xiàn)在我們就可以這樣調(diào)用了:

Amazing!而且你可以發(fā)現(xiàn),System.out.println(numStrs.toString()) 打印的居然是數(shù)組對(duì)象的字符串形式 —— 而不是數(shù)組對(duì)象的地址。查看反編譯后的 App.class,發(fā)現(xiàn)是將擴(kuò)展方法的調(diào)用,替換為靜態(tài)方法調(diào)用:

而數(shù)組的 toString 方法,使用的是 Manifold 為數(shù)組定義的擴(kuò)展方法 ManArrayExt.toString(@This Object array):

[Ljava.lang.String;@511d50c0 什么的,Goodbye,再也不見(jiàn)~

因?yàn)槭窃诰幾g期將擴(kuò)展方法的調(diào)用替換為靜態(tài)方法調(diào)用,所以使用 Manifold 的擴(kuò)展方法,即使調(diào)用方法的對(duì)象是 null 也沒(méi)有問(wèn)題,因?yàn)樘幚砗蟮拇a是把 null 作為參數(shù)傳遞到對(duì)應(yīng)的靜態(tài)方法。比如我們對(duì) Collection 進(jìn)行擴(kuò)展:

然后調(diào)用的時(shí)候:

java.lang.NullPointerException,Goodbye,再也不見(jiàn)~

數(shù)組擴(kuò)展方法

我們看到 List<@Self(true) Object> 這樣的寫(xiě)法:@Self 是用來(lái)表示被注解的值應(yīng)該是什么類型,如果是 @Self,即 @Self(false),表示被注解的值和 @This 注解的值是同一個(gè)類型;@Self(true) 則表示是數(shù)組中元素的類型。

對(duì)于對(duì)象數(shù)組,我們可以看到 toList 方法返回的就是對(duì)應(yīng)的 List(T 為數(shù)組元素的類型):

但如果是原始類型數(shù)組,IDEA 指示的返回值是:

但是我用的是 Java 啊,擦除法泛型怎么可能擁有 List 這么偉大的功能 —— 所以你只能用原生類型來(lái)接收這個(gè)返回值 :)

—— 許個(gè)愿,希望 Project Valhalla 早日 GA。

我們經(jīng)常在各個(gè)項(xiàng)目中看到,大家先把某個(gè)對(duì)象包裝成 Optional,然后進(jìn)行 filter、map 等。通過(guò) @Self 的類型映射,你可以這樣為 Object 加入一個(gè)非常實(shí)用的辦法:

那么任何對(duì)象,都將擁有 asOpt() 方法。

相比于之前的需要包裝一下的不自然:

你現(xiàn)在可以自然而然的使用 Optional:

當(dāng)然,Object 是所有的類的父類,這樣做是否合適,還是需要謹(jǐn)慎的思考一下。

擴(kuò)展靜態(tài)方法

我們都知道 Java9 給集合添加了工廠方法:

是不是很眼饞?因?yàn)槿绻玫牟皇?Java9 及以上版本(Java8:直接報(bào)我身份證就行),你就得用 Guava 之類的庫(kù) —— 然而 ImmutableList.of 用起來(lái)終究是比不上 List.of 這樣的正統(tǒng)來(lái)的自然。

沒(méi)關(guān)系,Manifold 說(shuō):“無(wú)所謂,我會(huì)出手”?;?Manifold 擴(kuò)展靜態(tài)方法,就是在擴(kuò)展類的靜態(tài)方法上,也加上 @Extension:

然后你就可以欺騙自己已經(jīng)用上了 Java8 之后的版本 —— 你發(fā)任你發(fā),我用 Java8。

BTW,因?yàn)?nbsp;Object 是所有類的父類,如果你給 Object 添加靜態(tài)擴(kuò)展方法,那么意味著你可以在任何地方直接訪問(wèn)到這個(gè)靜態(tài)方法,而不需要 import —— 恭喜你,解鎖了 “頂級(jí)函數(shù)”。

建議

我從 2019 年開(kāi)始關(guān)注 Manifold,那時(shí)候 Manifold IDEA 插件還是收費(fèi)的,所以當(dāng)時(shí)只是做了簡(jiǎn)單的嘗試。最近再看,IDEA 插件已經(jīng)完全免費(fèi),所以迫不及待地想要物盡其用。目前我已經(jīng)在一個(gè)項(xiàng)目中使用了 Manifold 來(lái)實(shí)現(xiàn)擴(kuò)展方法的功能 —— 當(dāng)事人表示非常上癮,已經(jīng)離不開(kāi)了。如果你有使用上的建議和疑問(wèn),歡迎和我一起討論。

謹(jǐn)慎添加擴(kuò)展方法

如果決定在項(xiàng)目中使用 Manifold 實(shí)現(xiàn)擴(kuò)展方法,那么我們一定要做到 “管住自己的手”。

首先,就是上文說(shuō)的,給 Object 或者其他在項(xiàng)目中使用非常廣泛的類添加擴(kuò)展方法,一定要非常的慎重,最好是要和項(xiàng)目組的同學(xué)一起討論,讓大家一起決定,否則很容易讓人迷惑。

另外,如果要給某個(gè)類添加擴(kuò)展方法,一定要先認(rèn)真思考一個(gè)問(wèn)題:“這個(gè)方法的邏輯是不是在這個(gè)類的職責(zé)范圍內(nèi),是否有摻雜業(yè)務(wù)自定義邏輯”。例如下面這個(gè)方法(判斷給定的字符串是不是一個(gè)合法的參數(shù)):

很明顯,isValidParam 不是 String 這個(gè)類的職責(zé)范圍,應(yīng)該把 isValidParam 繼續(xù)放在 XxxBizUtils 里面。當(dāng)然,如果你把方法名改成 isNotBlankAndNotEqualsIgnoreCaseNullLiteral,那是可以的 :) —— 不過(guò)勸你別這么做,容易被打。

以上就是詳解Java 缺失的特性擴(kuò)展方法的詳細(xì)內(nèi)容,更多關(guān)于Java 缺失特性擴(kuò)展方法的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • SpringBoot Web開(kāi)發(fā)之系統(tǒng)任務(wù)啟動(dòng)與路徑映射和框架整合

    SpringBoot Web開(kāi)發(fā)之系統(tǒng)任務(wù)啟動(dòng)與路徑映射和框架整合

    這篇文章主要介紹了SpringBoot Web開(kāi)發(fā)中的系統(tǒng)任務(wù)啟動(dòng)與路徑映射和Servlet、Filter、Listener框架整合,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • Java實(shí)現(xiàn)UDP多線程在線咨詢

    Java實(shí)現(xiàn)UDP多線程在線咨詢

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)UDP多線程在線咨詢,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-04-04
  • 關(guān)于Java垃圾回收開(kāi)銷降低的幾條建議

    關(guān)于Java垃圾回收開(kāi)銷降低的幾條建議

    垃圾回收(Garbage Collection)是Java虛擬機(jī)(JVM)垃圾回收器提供的一種用于在空閑時(shí)間不定時(shí)回收無(wú)任何對(duì)象引用的對(duì)象占據(jù)的內(nèi)存空間的一種機(jī)制,下面這篇文章主要介紹了關(guān)于Java垃圾回收開(kāi)銷降低的幾條建議,需要的朋友可以參考借鑒,下面來(lái)一起看看吧。
    2017-02-02
  • springboot掃描引入jar包的service等組件方式

    springboot掃描引入jar包的service等組件方式

    這篇文章主要介紹了springboot掃描引入jar包的service等組件方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • SpringBoot統(tǒng)一返回結(jié)果問(wèn)題

    SpringBoot統(tǒng)一返回結(jié)果問(wèn)題

    這篇文章主要介紹了SpringBoot統(tǒng)一返回結(jié)果問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • Java代碼中4種字符串拼接方式分析

    Java代碼中4種字符串拼接方式分析

    本文主要介紹了Java代碼中4種字符串拼接方式分析,主要介紹了“+”號(hào)、StringBuilder、StringJoiner、String#join,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • Java實(shí)現(xiàn)按鍵精靈的示例代碼

    Java實(shí)現(xiàn)按鍵精靈的示例代碼

    這篇文章主要為大家詳細(xì)介紹了如何利用Java語(yǔ)言實(shí)現(xiàn)按鍵精靈,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)或工作有一定的參考價(jià)值,感興趣的可以學(xué)習(xí)一下
    2022-05-05
  • Java設(shè)計(jì)模式UML之類圖精解

    Java設(shè)計(jì)模式UML之類圖精解

    在UML類圖中,類使用包含類名、屬性(field) 和方法(method) 且?guī)в蟹指罹€的矩形來(lái)表示,比如下圖表示一個(gè)Employee類,它包含name,age和email這3個(gè)屬性,以及modifyInfo()方法
    2022-02-02
  • Java大文本并行計(jì)算實(shí)現(xiàn)過(guò)程解析

    Java大文本并行計(jì)算實(shí)現(xiàn)過(guò)程解析

    這篇文章主要介紹了Java大文本并行計(jì)算如何實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-06-06
  • Java包裝類的緩存機(jī)制原理實(shí)例詳解

    Java包裝類的緩存機(jī)制原理實(shí)例詳解

    這篇文章主要介紹了Java包裝類的緩存機(jī)制原理實(shí)例詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-12-12

最新評(píng)論