最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解Java?缺失的特性擴展方法

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

什么是擴展方法

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

為什么需要擴展方法

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

傳統(tǒng)寫法:

使用 Stream 寫法:

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

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

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

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

代碼更容易閱讀,因為是鏈式調(diào)用,而不是用靜態(tài)方法套娃

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

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

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

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

準備條件

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

然后再在項目 pom 的 maven-compiler-plugin 中加入 annotationProcessorPaths:

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

編寫擴展方法

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

基于 Manifold,編寫擴展方法:

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

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

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

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

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

關(guān)于第 3 點,之所以有這個要求,是因為 Manifold 希望能快速找到項目中的擴展方法,避免對項目中所有的類進行注解掃描,提升處理的效率。

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

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

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

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

因為是在編譯期將擴展方法的調(diào)用替換為靜態(tài)方法調(diào)用,所以使用 Manifold 的擴展方法,即使調(diào)用方法的對象是 null 也沒有問題,因為處理后的代碼是把 null 作為參數(shù)傳遞到對應(yīng)的靜態(tài)方法。比如我們對 Collection 進行擴展:

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

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

數(shù)組擴展方法

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

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

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

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

—— 許個愿,希望 Project Valhalla 早日 GA。

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

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

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

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

當然,Object 是所有的類的父類,這樣做是否合適,還是需要謹慎的思考一下。

擴展靜態(tài)方法

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

是不是很眼饞?因為如果用的不是 Java9 及以上版本(Java8:直接報我身份證就行),你就得用 Guava 之類的庫 —— 然而 ImmutableList.of 用起來終究是比不上 List.of 這樣的正統(tǒng)來的自然。

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

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

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

建議

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

謹慎添加擴展方法

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

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

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

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

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

相關(guān)文章

  • SpringBoot過濾器如何獲取POST請求的JSON參數(shù)

    SpringBoot過濾器如何獲取POST請求的JSON參數(shù)

    這篇文章主要介紹了SpringBoot過濾器如何獲取POST請求的JSON參數(shù)操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • IDEA最新激活碼2021(IDEA2020.3.2最新永久激活方法)

    IDEA最新激活碼2021(IDEA2020.3.2最新永久激活方法)

    這篇文章主要介紹了IDEA最新激活碼2021(IDEA2020.3.2最新永久激活方法),本文通過實例圖文相結(jié)合給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-12-12
  • 23種設(shè)計模式(13)java觀察者模式

    23種設(shè)計模式(13)java觀察者模式

    這篇文章主要為大家詳細介紹了23種設(shè)計模式之java觀察者模式,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-12-12
  • Java任務(wù)定時執(zhí)行器案例的實現(xiàn)

    Java任務(wù)定時執(zhí)行器案例的實現(xiàn)

    定時器會執(zhí)行指定的任務(wù),本文主要介紹了Java任務(wù)定時執(zhí)行器案例的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06
  • mybatis主表與明細表一對多的同時插入操作方法

    mybatis主表與明細表一對多的同時插入操作方法

    對主表(采購申請表)和明細表(申請物資表)同時進行插入操作insert,怎么實現(xiàn)呢,下面給大家分享mybatis主表與明細表一對多的同時插入操作方法,感興趣的朋友一起看看吧
    2023-02-02
  • Spring Boot使用Allatori代碼混淆的方法

    Spring Boot使用Allatori代碼混淆的方法

    這篇文章主要介紹了Spring Boot使用Allatori代碼混淆的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-03-03
  • Java9垃圾回收方法finalize() 原理解析

    Java9垃圾回收方法finalize() 原理解析

    這篇文章主要介紹了Java9垃圾回收方法finalize() 原理解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-02-02
  • 淺談Java枚舉的作用與好處

    淺談Java枚舉的作用與好處

    下面小編就為大家?guī)硪黄獪\談Java枚舉的作用與好處。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-07-07
  • Java中可以實現(xiàn)負載均衡的算法詳解

    Java中可以實現(xiàn)負載均衡的算法詳解

    這篇文章主要介紹了Java中可以實現(xiàn)負載均衡的算法詳解,在Java中,有多種算法可以實現(xiàn)負載均衡,下面是兩個常見的算法示例,隨機算法和輪詢算法,需要的朋友可以參考下
    2023-08-08
  • java?并發(fā)線程個數(shù)的如何確定

    java?并發(fā)線程個數(shù)的如何確定

    這篇文章主要介紹了java?并發(fā)線程個數(shù)的如何確定,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12

最新評論

台江县| 关岭| 女性| 五台县| 新巴尔虎右旗| 翼城县| 合江县| 阿城市| 宁德市| 东光县| 潜山县| 忻州市| 台东县| 兴海县| 高阳县| 岳阳市| 资溪县| 旺苍县| 三江| 拉孜县| 鸡东县| 霍林郭勒市| 油尖旺区| 曲周县| 崇左市| 班玛县| 宜昌市| 民勤县| 庆城县| 兰坪| 惠来县| 百色市| 辽宁省| 保亭| 雅江县| 房山区| 共和县| 闽清县| 都兰县| 石狮市| 永定县|