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

關(guān)于泛型擦除問題的解決--Mybatis查詢類型轉(zhuǎn)換

 更新時間:2022年08月25日 14:22:53   作者:keep丶  
這篇文章主要介紹了關(guān)于泛型擦除問題的解決--Mybatis查詢類型轉(zhuǎn)換方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

概念介紹

Java語言的泛型采用的是擦除法實現(xiàn)的偽泛型,泛型信息(類型變量、參數(shù)化類型)編譯之后通通被除掉了。使用擦除法的好處就是實現(xiàn)簡單、非常容易Backport,運行期也能夠節(jié)省一些類型所占的內(nèi)存空間。

而擦除法的壞處就是,通過這種機制實現(xiàn)的泛型遠(yuǎn)不如真泛型靈活和強大。Java選取這種方法是一種折中,因為Java最開始的版本是不支持泛型的,為了兼容以前的庫而不得不使用擦除法。

驗證擦除,我們編寫下面代碼:

public class ErasedTypeEquivalence {
    public static void main(String[] args) {
    	//例1
        ArrayList<String> list1 = new ArrayList<String>();
        list1.add("abc");
        ArrayList<Integer> list2 = new ArrayList<Integer>();
        list2.add(123);
        System.out.println(list1.getClass() == list2.getClass());//true
		
		//例2
		ArrayList<Integer> list = new ArrayList<Integer>();
        list.add(1);  //這樣調(diào)用 add 方法只能存儲整形,因為泛型類型的實例為 Integer
        list.getClass().getMethod("add", Object.class).invoke(list, "asd");
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));//會輸出1和asd
        }
    }
}

在例1中,我們定義了兩個ArrayList數(shù)組,不過一個是ArrayList<String>泛型類型的,只能存儲字符串;一個是ArrayList<Integer>泛型類型的,只能存儲整數(shù),最后,我們通過list1對象和list2對象的getClass()方法獲取他們的類的信息,最后發(fā)現(xiàn)結(jié)果為true。說明泛型類型String和Integer都被擦除掉了,只剩下原始類型。       

在例2中,定義了一個ArrayList泛型類型實例化為Integer對象,如果直接調(diào)用add()方法,那么只能存儲整數(shù)數(shù)據(jù),不過當(dāng)我們利用反射調(diào)用add()方法的時候,卻可以存儲字符串,這說明了Integer泛型實例在編譯之后被擦除掉了,只保留了原始類型。

上面兩次提到了原始類型,什么是原始類型?原始類型 就是擦除去了泛型信息,最后在字節(jié)碼中的類型變量的真正類型,無論何時定義一個泛型,相應(yīng)的原始類型都會被自動提供,類型變量擦除,并使用其限定類型(無限定的變量用Object)替換。

問題案例

最近在搭系統(tǒng)基礎(chǔ)代碼架構(gòu),其中就涉及到系統(tǒng)數(shù)據(jù)字典 功能,以前都是用varchar類型保存字典內(nèi)容,這次準(zhǔn)備玩點新花樣,準(zhǔn)備用上MySQL的JSON類型保存字典表的內(nèi)容字段。>>文章傳送門<<

實際操作之后就遇到了泛型擦除問題,如下圖,我雖然對content字段的List指定了泛型DictContent,但是在做類型轉(zhuǎn)換時,只能指定javaType=List,沒有也不能指定其泛型:

在沒有指定泛型的情況下,JacksonTypeHandler在做類型轉(zhuǎn)換后生成的集合的泛型就與預(yù)期的不一致:

原因分析

原因很簡單,在resultMap中指定的JavaType是java.util.List,此處只能指定類類型,并不能指定泛型。而在對應(yīng)的類型轉(zhuǎn)換類中也沒有指定其泛型,而List<DictContent>和List<Object>的類類型是一樣的,所以在給content字段賦值時是不會報錯的。但是一旦你需要操作List的中的元素,在取出元素時,JVM就發(fā)現(xiàn)你要的類型是DictContent 而實際上是LinkedHashMap,就會拋出類型轉(zhuǎn)換異常。

通俗的講就是你準(zhǔn)備買華為手機(將JSON類型轉(zhuǎn)成List<DictContent>類型),但是買的時候沒有說要買什么牌子的手機(在javaType中只指定了List類型,沒有也無法指定泛型),而店子里有很多牌子的手機,所以店家就隨便給了你一款手機。。。

以下是Mybatis Plus中的部分源碼,可以看到在沒有指定List的泛型的情況下,通過JacksonTypeHandler處理后的元素類型并不是我們預(yù)期的類型:

下圖我們可以看到JacksonTypeHandler是BaseTypeHandler的子類,而且指定了BaseTypeHandler中的泛型是Object類型,但是上圖中的泛型卻是LinkedHashMap。

至于為什么是LinkedHashMap,我覺得是JVM指定的,如果哪位大佬比較清楚這塊的邏輯還請在評論中指點一下!

解決方案

既然原因搞清楚了,解決方案就呼之欲出了,有兩種方案:

  • 自定義一個指定泛型的集合類替代List<T>
  • 引用上文中通俗的說法,這個方案就是在買手機的時候告訴賣家,我要買華為手機。
  • 自定義一個指定泛型的TypeHandler類替代JacksonTypeHandler類
  • 而這里的的通俗的說法就是讓店家只賣華為手機。

以上兩種方案都可以實現(xiàn)我們的需求。

從工作量上來說,自定義一個List<T>顯然更少,所以我選擇了第一種方案,如圖:

8.11新增:第二種解決方式:

替換后結(jié)果如下:

至此,泛型擦除問題解決。 

總結(jié)

不得不說,玩新花樣總是會遇到各種各樣的坑,但是編程之路,不就是不斷的踩坑,不斷的改BUG,積累經(jīng)驗,打怪升級。如果不是因為最近玩了這個新花樣,可能我這輩子都不會遇到泛型擦除的問題!       

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • java使用selenium自動化WebDriver等待的示例代碼

    java使用selenium自動化WebDriver等待的示例代碼

    顯式等待和隱式等待是WebDriver中兩種常用的等待方式,它們都可以用來等待特定的條件滿足后再繼續(xù)執(zhí)行代碼,本文給大家介紹java使用selenium自動化WebDriver等待,感興趣的朋友一起看看吧
    2023-09-09
  • 詳解Java8新特性如何防止空指針異常

    詳解Java8新特性如何防止空指針異常

    要說 Java 編程中哪個異常是你印象最深刻的,那 NullPointerException 空指針可以說是臭名昭著的,不要說初級程序員會碰到, 即使是中級,專家級程序員稍不留神,就會掉入這個坑里,本文就和大家聊聊Java8新特性如何防止空指針異常
    2023-08-08
  • java中的GC收集器詳情

    java中的GC收集器詳情

    這篇文章主要介紹了java中的GC收集器,GC(Garbage collection )指的是程序內(nèi)存管理分手動和自動,手動內(nèi)存管理,需要我們編程的時候顯式分配和釋放空間,但如果忘記釋放,會造成嚴(yán)重的內(nèi)存泄漏問題,下面文章內(nèi)容我們就來實例說明情況,需要的朋友可以參考一下
    2021-10-10
  • SpringCache緩存自定義配置的實現(xiàn)

    SpringCache緩存自定義配置的實現(xiàn)

    本文主要介紹了SpringCache緩存自定義配置的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • Eclipse中實現(xiàn)JS代碼提示功能(圖文教程)

    Eclipse中實現(xiàn)JS代碼提示功能(圖文教程)

    本文通過圖文并茂的形式給大家介紹了Eclipse中實現(xiàn)JS代碼提示功能,非常不錯,具有參考借鑒價值,需要的朋友參考下吧
    2017-11-11
  • SSM項目實現(xiàn)短信驗證碼登錄功能的示例代碼

    SSM項目實現(xiàn)短信驗證碼登錄功能的示例代碼

    這篇文章主要為大家分享了在SSM項目中實現(xiàn)短信驗證碼登錄功能的示例代碼,文中的實現(xiàn)步驟講解詳細(xì),感興趣的小伙伴可以跟隨小編一起動手嘗試一下
    2022-05-05
  • 淺聊一下Spring中Bean的配置細(xì)節(jié)

    淺聊一下Spring中Bean的配置細(xì)節(jié)

    我們知道,當(dāng)寫完一個普通的 Java 類后,想讓 Spring IoC 容器在創(chuàng)建類的實例對象時使用構(gòu)造方法完成實例對象的依賴注入,那么就需要在配置元數(shù)據(jù)中寫好類的 Bean 定義,包括各種標(biāo)簽的屬性。所以本文我們來說說這其中的配置細(xì)節(jié),需要的朋友可以參考下
    2023-07-07
  • Java編譯器用maven打war包出錯解決辦法

    Java編譯器用maven打war包出錯解決辦法

    這篇文章主要介紹了用maven打war包出錯的解決辦法,需要的朋友可以參考下
    2018-03-03
  • Netty分布式客戶端接入流程初始化源碼分析

    Netty分布式客戶端接入流程初始化源碼分析

    這篇文章主要介紹了Netty分布式客戶端接入流程初始化源碼分析,有關(guān)channelConfig有關(guān)的初始化過程剖析,有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2022-03-03
  • springboot全局字符編碼設(shè)置方式(解決亂碼問題)

    springboot全局字符編碼設(shè)置方式(解決亂碼問題)

    這篇文章主要介紹了springboot全局字符編碼設(shè)置方式(解決亂碼問題),具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-12-12

最新評論

东乡族自治县| 海盐县| 兴安县| 海林市| 扎赉特旗| 临泽县| 文成县| 启东市| 平阴县| 新疆| 姚安县| 师宗县| 南岸区| 鹰潭市| 成安县| 定安县| 尚义县| 静安区| 大新县| 新余市| 莱芜市| 东兴市| 梁平县| 同仁县| 普宁市| 洪湖市| 哈巴河县| 无棣县| 杂多县| 桃源县| 静乐县| 德格县| 北海市| 南安市| 和林格尔县| 宜州市| 河间市| 兴城市| 石屏县| 龙州县| 绵竹市|