亚洲一级免费看,特黄特色大片免费观看播放器,777毛片,久久久久国产一区二区三区四区,欧美三级一区二区,国产精品一区二区久久久久,人人澡人人草

java語言

Java的泛型擦除和運(yùn)行時(shí)泛型信息獲取

時(shí)間:2025-04-29 00:27:53 java語言 我要投稿
  • 相關(guān)推薦

Java的泛型擦除和運(yùn)行時(shí)泛型信息獲取

  只要理解了 Java 引入泛型擦除的原因,也自然能理解如何在運(yùn)行時(shí)獲取泛型信息了。下面是小編為大家?guī)淼腏ava的泛型擦除和運(yùn)行時(shí)泛型信息獲取的知識(shí),歡迎閱讀。

  Java 的泛型擦除

  程序員界有句流行的話,叫 talk is cheap, show me the code,所以話不多說,看代碼。

  代碼一

  Java代碼

  Class c1 = new ArrayList().getClass();

  Class c2 = new ArrayList().getClass();

  System.out.println(c1 == c2);

  /* Output

  true

  */

  ArrayList 和 ArrayList 在編譯的時(shí)候是完全不同的類型。你無法在寫代碼時(shí),把一個(gè) String 類型的實(shí)例加到 ArrayList 中。但是在程序運(yùn)行時(shí),的的確確會(huì)輸出true。

  這就是 Java 泛型的類型擦除造成的,因?yàn)椴还苁?ArrayList 還是 ArrayList,在編譯時(shí)都會(huì)被編譯器擦除成了 ArrayList。Java 之所以要避免在創(chuàng)建泛型實(shí)例時(shí)而創(chuàng)建新的類,從而避免運(yùn)行時(shí)的過度消耗。

  代碼二

  Java代碼

  List list = new ArrayList();

  Map map = new HashMap();

  System.out.println(Arrays.toString(list.getClass().getTypeParameters()));

  System.out.println(Arrays.toString(map.getClass().getTypeParameters()));

  /* Output

  [E]

  [K, V]

  */

  我們可能期望能夠獲得真實(shí)的泛型參數(shù),但是僅僅獲得了聲明時(shí)泛型參數(shù)占位符。getTypeParameters 方法的 Javadoc 也是這么解釋的:僅返回聲明時(shí)的泛型參數(shù)。所以,通過 getTypeParamters 方法無法獲得運(yùn)行時(shí)的泛型信息。

  運(yùn)行泛型信息的獲取

  但是在有些場(chǎng)景中,我們還是需要獲取泛型信息的。比如,在調(diào)用 HTTP 或 RPC 接口時(shí),我們需要進(jìn)行序列化和反序列的工作。

  例如,我們通過一個(gè) HTTP 接口接收如下的 JSON 數(shù)據(jù)

  Java代碼

  [{

  "name": "Stark",

  "nickName": "Iron Man"

  },

  {

  "name": "Rogers",

  "nickName": "Captain America"

  }]

  我們需要將其映射為 List。

  但是之前我們提到了泛型擦除,那我們所使用的 HTTP 或 RPC 框架是如何獲取 List 中的泛型信息呢?

  再看一段代碼

  Java代碼

  Map map = new HashMap() {};

  Type type = map.getClass().getGenericSuperclass();

  ParameterizedType parameterizedType = ParameterizedType.class.cast(type);

  for (Type typeArgument : parameterizedType.getActualTypeArguments()) {

  System.out.println(typeArgument.getTypeName());

  }

  /* Output

  java.lang.String

  java.lang.Integer

  */

  上面這段代碼展示了如何獲取 map 這個(gè)實(shí)例所對(duì)應(yīng)類的泛型信息。顯然,這次我們成功獲得了其中泛型參數(shù)信息。有了這些泛型參數(shù),上面所提到的序列化和反序列化工作就是可能的了。

  那為什么之前不可以,而這次可以了呢?請(qǐng)注意一個(gè)細(xì)節(jié)

  上一節(jié)的變量聲明

  Java代碼

  Map map = new HashMap();

  本節(jié)的變量聲明

  Java代碼

  Map map = new HashMap() {};

  其中最關(guān)鍵的差別是本節(jié)的變量聲明多了一對(duì)大括號(hào)。有一定 Java 基礎(chǔ)的同學(xué)都能看出本節(jié)的變量聲明其實(shí)是創(chuàng)建了一個(gè)匿名內(nèi)部類。這個(gè)類是 HashMap 的子類,泛型參數(shù)限定為了 String 和 Integer。

  其實(shí)在“泛型擦除”一節(jié),我們已經(jīng)提到,Java 引入泛型擦除的原因是避免因?yàn)橐敕盒投鴮?dǎo)致運(yùn)行時(shí)創(chuàng)建不必要的類。那我們其實(shí)就可以通過定義類的方式,在類信息中保留泛型信息,從而在運(yùn)行時(shí)獲得這些泛型信息。

  簡(jiǎn)而言之,Java 的泛型擦除是有范圍的,即類定義中的泛型是不會(huì)被擦除的。

  框架中的應(yīng)用

  其實(shí)很多框架就是使用類定義中的泛型不會(huì)被擦除這個(gè)特性,實(shí)現(xiàn)了相應(yīng)的功能。

  例如,Spring Web 模塊的 RestTemplate,我們可以使用如下寫法:

  Java代碼

  ResponseEntity responseEntity = restTemplate.exchange(url, HttpMethod.GET, null, new ParameterizedTypeReference() {});

  其中的 new ParameterizedTypeReference() {} 就是通過定義一個(gè)匿名內(nèi)部類的方式來獲得泛型信息,從而進(jìn)行反序列化的工作。

  總結(jié)

  Java 泛型擦除是 Java 泛型中的一個(gè)重要特性,其目的是避免過多的創(chuàng)建類而造成的運(yùn)行時(shí)的過度消耗。所以,想 ArrayList 和 ArrayList 這兩個(gè)實(shí)例,其類實(shí)例是同一個(gè)。

  但很多情況下我們又需要在運(yùn)行時(shí)獲得泛型信息,那我們可以通過定義類的方式(通常為匿名內(nèi)部類,因?yàn)槲覀儎?chuàng)建這個(gè)類只是為了獲得泛型信息)在運(yùn)行時(shí)獲得泛型參數(shù),從而滿足例如序列化、反序列化等工作的需要。

  只要理解了 Java 引入泛型擦除的原因,也自然能理解如何在運(yùn)行時(shí)獲取泛型信息了。


【Java的泛型擦除和運(yùn)行時(shí)泛型信息獲取】相關(guān)文章:

講解Java的泛型07-13

java泛型方法10-22

Java泛型是什么10-17

java泛型方法推薦05-25

java編譯器的泛型08-09

初步理解Java的泛型特性分享10-09

Java8自定義帶泛型的函數(shù)式接口08-02

java布爾型介紹10-16

專業(yè)型碩士和學(xué)術(shù)型碩士有哪些區(qū)別11-20