溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Java缺失的特性擴(kuò)展方法是什么

發(fā)布時(shí)間:2023-05-06 11:34:04 來源:億速云 閱讀:120 作者:iii 欄目:開發(fā)技術(shù)

今天小編給大家分享一下Java缺失的特性擴(kuò)展方法是什么的相關(guān)知識點(diǎn),內(nèi)容詳細(xì),邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。

    什么是擴(kuò)展方法

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

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

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

    傳統(tǒng)寫法:

    使用 Stream 寫法:

    假設(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)行連接),那我們將可以這樣寫代碼:

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

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

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

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

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

    我們先來問問最近大火的 ChatGPT:

    Java缺失的特性擴(kuò)展方法是什么

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

    Manifold

    準(zhǔn)備條件

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

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

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

    編寫擴(kuò)展方法

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

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

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

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

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

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

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

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

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

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

    Java缺失的特性擴(kuò)展方法是什么

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

    Java缺失的特性擴(kuò)展方法是什么

    [Ljava.lang.String;@511d50c0 什么的,Goodbye,再也不見~

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

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

    java.lang.NullPointerException,Goodbye,再也不見~

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

    Java缺失的特性擴(kuò)展方法是什么

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

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

    Java缺失的特性擴(kuò)展方法是什么

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

    Java缺失的特性擴(kuò)展方法是什么

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

    Java缺失的特性擴(kuò)展方法是什么

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

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

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

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

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

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

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

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

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

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

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

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

    以上就是“Java缺失的特性擴(kuò)展方法是什么”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學(xué)習(xí)更多的知識,請關(guān)注億速云行業(yè)資訊頻道。

    向AI問一下細(xì)節(jié)

    免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

    AI