自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

詳解Java泛型之十分鐘理解泛型擦除

開發(fā) 后端
泛型信息只存在于代碼編譯階段,但是在java的運行期(已經(jīng)生成字節(jié)碼文件后)與泛型相關(guān)的信息會被擦除掉,專業(yè)術(shù)語叫做類型擦除。

[[408512]]

今天我們來講解泛型中另一個重要知識點——泛型擦除!

泛型擦除概念

泛型信息只存在于代碼編譯階段,但是在java的運行期(已經(jīng)生成字節(jié)碼文件后)與泛型相關(guān)的信息會被擦除掉,專業(yè)術(shù)語叫做類型擦除。我們來看一個例子:

  1. ArrayList<Integer> l1 = new ArrayList(); 
  2. ArrayList<String> l2 = new ArrayList();  
  3. System.out.println(l1.getClass()==l2.getClass()); 

 運行代碼,結(jié)果為True

這是因為ArrayList <String>和ArrayList <Integer>在 jvm 中的 Class 都是 List.class,二者在 jvm 中等同于List<Object> 。

通過下面的例子我們做進一步的分析

  1. import java.lang.reflect.Field; 
  2. public class GeneErasure<T> { 
  3.    T object; 
  4.    public GeneErasure(T object) { 
  5.       this.object = object; 
  6.    } 
  7.    public static void main(String[] args) { 
  8.       GeneErasure demo = new GeneErasure<String>("hi"); 
  9.       Class classz = demo.getClass(); 
  10.       System.out.println(classz.getName()); 
  11.       //輸出com.my.generic.GeneErasure 
  12.       Field[] fs = classz.getDeclaredFields(); 
  13.       for ( Field f:fs) { 
  14.         System.out.println("feild: "+f.getName()+"type:"+f.getType().getName()); 
  15.         //輸出feild: object type:java.lang.Object 
  16.       } 
  17.    } 

 通過這個例子我們可以看到Class 的類型仍然是GeneErasure并不是GeneErasure <T>這種形式,而類型T被替換成 Object 類型。接下來我們做另一個嘗試,把GeneErasure<T> 更改為 GeneErasure < T extends String>

輸出結(jié)果為:

  1. feild: object type:java.lang.String 

所以,在泛型類被類型擦除的時候,之前泛型類中的類型參數(shù)部分如果沒有指定上限,如<T>則會被轉(zhuǎn)譯成普通的Object 類型,如果指定了上限,如<T extends String>則類型參數(shù)就被替換成類型上限。

利用類型擦除干“壞事兒”

大家都知道,下面這段代碼l.add(123)無法編譯通過,因為123不是String類型,這也是使用泛型的好處之一。

  1. ArrayList<String> l=new ArrayList<String>(); 
  2.  
  3. l.add("abc"); 
  4.  
  5. l.add(123); 

但是我們理解了泛型擦除的原理,我們可以巧妙地利用這個原理結(jié)合反射知識干一些“壞事”,例如:

  1. ArrayList<String>l=new ArrayList<String>(); 
  2.      l.add("abc");    
  3.      try { 
  4.        Method method = l.getClass().getDeclaredMethod("add",Object.class); 
  5.        method.invoke(l,"test"); 
  6.        method.invoke(l,100.f); 
  7.      }catch (Exception e) { 
  8.        e.printStackTrace(); 
  9.      } 
  10.      System.out.println("list的大小是:"+l.size());  
  11.      for ( Object o: l){ 
  12.        System.out.println(o); 
  13.      } 

 運行結(jié)果是:

  1. list的大小是:3 
  2.  
  3. abc 
  4.  
  5. test 
  6.  
  7. 100.0(被成功插入到ArrayList中) 

我們可以看見100.0 成功地插入到ArrayList <String> 中了,所以利用類型擦除的原理并結(jié)合反射的手段就繞過了正常開發(fā)中編譯器不允許的操作限制。

通俗的理解

我們可以將泛型比作是一個看守,他來守護我們的代碼安全,然后設(shè)置各項規(guī)定,“xxx 禁止出入”的提醒。而現(xiàn)實生活中,也總會有些人能夠基于對門衛(wèi)們生活作息的規(guī)律,繞開他們的監(jiān)視(反射結(jié)合泛型擦除)來干一些壞事兒 。

 

責(zé)任編輯:姜華 來源: 今日頭條
相關(guān)推薦

2024-06-19 09:58:29

2013-05-03 10:57:09

泛型泛型教程

2019-04-01 14:59:56

負(fù)載均衡服務(wù)器網(wǎng)絡(luò)

2016-06-13 14:07:50

Java動態(tài)代理

2020-09-29 06:37:30

Java泛型

2017-11-14 14:41:11

Java泛型IO

2021-06-18 08:25:42

Java泛型通配符

2022-03-23 09:32:38

微服務(wù)容器Kubernetes

2020-12-17 06:48:21

SQLkafkaMySQL

2021-07-09 06:11:37

Java泛型Object類型

2020-09-27 14:41:37

C語言編程語言計算機

2021-06-17 06:51:32

Java泛型Java編程

2021-09-07 09:40:20

Spark大數(shù)據(jù)引擎

2022-06-16 07:31:41

Web組件封裝HTML 標(biāo)簽

2023-04-12 11:18:51

甘特圖前端

2016-01-04 11:18:00

KubernetesKubernetes概容器技術(shù)

2012-07-10 01:22:32

PythonPython教程

2015-09-06 09:22:24

框架搭建快速高效app

2024-05-13 09:28:43

Flink SQL大數(shù)據(jù)

2023-11-30 10:21:48

虛擬列表虛擬列表工具庫
點贊
收藏

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