成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

掌握J(rèn)ava-TypeToken原理及泛型擦除

開(kāi)發(fā) 后端
借助對(duì)TypeToken原理的分析,加強(qiáng)對(duì)泛型擦除的理解,使得我們能夠知道什么時(shí)候,通過(guò)什么方式可以獲取到泛型的類(lèi)型。

 [[359081]]

概要

借助對(duì)TypeToken原理的分析,加強(qiáng)對(duì)泛型擦除的理解,使得我們能夠知道什么時(shí)候,通過(guò)什么方式可以獲取到泛型的類(lèi)型。

泛型擦除

眾所周知,Java的泛型只在編譯時(shí)有效,到了運(yùn)行時(shí)這個(gè)泛型類(lèi)型就會(huì)被擦除掉,即List<String>和List<Integer>在運(yùn)行時(shí)其實(shí)都是List<Object>類(lèi)型。

為什么選擇這種實(shí)現(xiàn)機(jī)制?不擦除不行么?在Java誕生10年后,才想實(shí)現(xiàn)類(lèi)似于C++模板的概念,即泛型。Java的類(lèi)庫(kù)是Java生態(tài)中非常寶貴的財(cái)富,必須保證向后兼容(即現(xiàn)有的代碼和類(lèi)文件依舊合法)和遷移兼容(泛化的代碼和非泛化的代碼可互相調(diào)用)基于上面這兩個(gè)背景和考慮,Java設(shè)計(jì)者采取了“類(lèi)型擦除”這種折中的實(shí)現(xiàn)方式。

同時(shí)正正有這個(gè)這么“坑”的機(jī)制,令到我們無(wú)法在運(yùn)行期間隨心所欲的獲取到泛型參數(shù)的具體類(lèi)型。

TypeToken

使用

使用過(guò)Gson的同學(xué)都知道在反序列化時(shí)需要定義一個(gè)TypeToken類(lèi)型,像這樣 

  1. private Type type = new TypeToken<List<Map<String, Foo>>>(){}.getType();  
  2. //調(diào)用fromJson方法時(shí)把type傳過(guò)去,如果type的類(lèi)型和json保持一致,則可以反序列化出來(lái)  
  3. gson.fromJson(json, type); 

三個(gè)問(wèn)題

1.為什么要用TypeToken來(lái)定義反序列化的類(lèi)型?正如上面說(shuō)的,如果直接把List<Map<String, Foo>>的類(lèi)型傳過(guò)去,但是因?yàn)檫\(yùn)行時(shí)泛型被擦除了,所以得到的其實(shí)是List<Object>,那么后面的Gson就不知道要轉(zhuǎn)成Map<String, Foo>類(lèi)型了,這時(shí)Gson會(huì)默認(rèn)轉(zhuǎn)成LinkedTreeMap類(lèi)型。

2.為什么帶有大括號(hào){}?這個(gè)大括號(hào)就是精髓所在。大家都知道,在Java語(yǔ)法中,在這個(gè)語(yǔ)境,{}是用來(lái)定義匿名類(lèi),這個(gè)匿名類(lèi)是繼承了TypeToken類(lèi),它是TypeToken的子類(lèi)。

3.為什么要通過(guò)子類(lèi)來(lái)獲取泛型的類(lèi)型?這是TypeToken能夠獲取到泛型類(lèi)型的關(guān)鍵,這是一個(gè)巧妙的方法。這個(gè)想法是這樣子的,既然像List<String>這樣中的泛型會(huì)被擦除掉,那么我用一個(gè)子類(lèi)SubList extends List<String>這樣的話(huà),在JVM內(nèi)部中會(huì)不會(huì)把父類(lèi)泛型的類(lèi)型給保存下來(lái)呢?

我這個(gè)子類(lèi)需要繼承的父類(lèi)的泛型都是已經(jīng)確定了的呀,果然,JVM是有保存這部分信息的,它是保存在子類(lèi)的Class信息中。

具體看:

https://stackoverflow.com/questions/937933/where-are-generic-types-stored-in-java-class-files

那么我們?cè)趺传@取這部分信息呢?還好,Java有提供API出來(lái): 

  1. Type mySuperClass = foo.getClass().getGenericSuperclass();  
  2. Type type = ((ParameterizedType)mySuperClass).getActualTypeArguments()[0];  
  3. System.out.println(type); 

分析一下這段代碼,Class類(lèi)的getGenericSuperClass()方法的注釋是:

Returns the Type representing the direct superclass of the entity (class, interface, primitive type or void) represented by thisClass. If the superclass is a parameterized type, the Type object returned must accurately reflect the actual type parameters used in the source code. The parameterized type representing the superclass is created if it had not been created before. See the declaration of ParameterizedType for the semantics of the creation process for parameterized types. If thisClass represents either theObject class, an interface, a primitive type, or void, then null is returned. If this object represents an array class then theClass object representing theObject class is returned

概括來(lái)說(shuō)就是對(duì)于帶有泛型的class,返回一個(gè)ParameterizedType對(duì)象,對(duì)于Object、接口和原始類(lèi)型返回null,對(duì)于數(shù) 組class則是返回Object.class。ParameterizedType是表示帶有泛型參數(shù)的類(lèi)型的Java類(lèi)型,JDK1.5引入了泛型之 后,Java中所有的Class都實(shí)現(xiàn)了Type接口,ParameterizedType則是繼承了Type接口,所有包含泛型的Class類(lèi)都會(huì)實(shí)現(xiàn) 這個(gè)接口。

自己調(diào)試一下就知道它返回的是什么了。

原理

核心的方法就是剛剛說(shuō)的那兩句,剩下的就很簡(jiǎn)單了。我們看看TypeToken的getType方法 

  1. public final Type getType() {  
  2.  //直接返回type  
  3.     return type;  
  4.   } 

看type的初始化 

  1. //注意這里用了protected關(guān)鍵字,限制了只有子類(lèi)才能訪問(wèn)  
  2. protected TypeToken() {  
  3.     this.type = getSuperclassTypeParameter(getClass());  
  4.     this.rawType = (Class<? super T>) $Gson$Types.getRawType(type);  
  5.     this.hashCode = type.hashCode();  
  6.   }    
  7.   //getSuperclassTypeParameter方法  
  8.   //這幾句就是上面的說(shuō)到  
  9.   static Type getSuperclassTypeParameter(Class<?> subclass) {  
  10.     Type superclass = subclass.getGenericSuperclass();  
  11.     if (superclass instanceof Class) {  
  12.       throw new RuntimeException("Missing type parameter.");  
  13.     }  
  14.     ParameterizedType parameterized = (ParameterizedType) superclass;  
  15.     //這里注意一下,返回的是Gson自定義的,在$Gson$Types里面定義的TypeImpl等,這個(gè)類(lèi)都是繼承Type的。  
  16.     return $Gson$Types.canonicalize(parameterized.getActualTypeArguments()[0]);  
  17.   } 

總結(jié)

在了解原理之后,相信大家都知道怎么去獲取泛型的類(lèi)型了。 

 

責(zé)任編輯:龐桂玉 來(lái)源: Java知音
相關(guān)推薦

2021-07-01 06:47:30

Java泛型泛型擦除

2021-09-29 18:17:30

Go泛型語(yǔ)言

2023-03-06 08:33:24

IDEA反編譯類(lèi)型

2021-07-29 09:20:18

Java泛型String

2019-09-04 00:20:10

JSON泛型擦除

2024-06-07 10:05:31

2017-03-06 16:51:52

Java泛型實(shí)現(xiàn)

2025-05-30 02:31:00

2025-01-13 07:00:00

Java泛型編程

2021-08-24 08:05:41

泛型類(lèi)型擦除Class

2024-01-15 08:28:31

Spring事件

2022-03-02 14:41:03

泛型反序列化

2009-09-25 10:03:51

Java泛型

2009-08-24 11:35:20

C# 泛型應(yīng)用

2009-08-24 10:37:27

C# 泛型

2009-12-24 09:16:11

C#泛型

2022-06-14 09:01:06

TypeScript泛型

2023-11-20 13:51:00

泛型函數(shù)TypeScript

2021-12-30 19:34:15

Java泛型JDK

2011-06-03 08:49:54

Java
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 国产精品久久久久久久久久久久久久 | 91久操视频 | 福利av在线 | www.国产一区 | 久久av在线播放 | 欧美 日韩 亚洲91麻豆精品 | 成人深夜小视频 | 亚洲一区 中文字幕 | 国产成人高清成人av片在线看 | 夜夜爽99久久国产综合精品女不卡 | 老司机深夜福利网站 | 成年视频在线观看 | 一级特黄视频 | caoporn免费在线视频 | 九九亚洲 | 一区二区三区视频在线免费观看 | 综合久久综合久久 | 久草影视在线 | 色妹子综合网 | 91成人免费 | 一级毛片在线看 | 欧美小视频在线观看 | 欧美jizzhd精品欧美巨大免费 | 欧美性高潮 | 精品中文字幕在线 | 中国一级毛片免费 | 久久成人综合 | av在线免费观看网站 | 国产成人精品综合 | 国产精品久久国产精品久久 | 一区中文字幕 | 偷拍第一页 | 亚洲黄色av网站 | 国产精品美女一区二区三区 | 夏同学福利网 | 一级大片 | 久久天天| 黄色成人在线网站 | 羞羞视频网站免费观看 | 久久久久9999 | 久久69精品久久久久久久电影好 |