国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

基礎篇:深入解析Java泛型

開發 后端
先了解下java的Type類型體系(類的類=>類型),Type是所有類型(原生類型-Class、參數化類型-Parameterizedtype、數組類型-GenericArrayType、類型變量-TypeVariable、基本類型-Class)的共同接口;前兩篇反射和注解講到的Class就是Type的一實現類。

[[347300]]

本文轉載自微信公眾號「潛行前行」,作者cscw 。轉載本文請聯系潛行前行公眾號。  

 1 JAVA的Type類型體系

先了解下java的Type類型體系(類的類=>類型),Type是所有類型(原生類型-Class、參數化類型-Parameterizedtype、數組類型-GenericArrayType、類型變量-TypeVariable、基本類型-Class)的共同接口;前兩篇反射和注解講到的Class就是Type的一實現類

  • Type下面又有四個子接口類ParameterizedType、TypeVariable、GenericArrayType、WildcardType
    • List表示泛型,E是TypeVariable類型,List則是ParameterizedType(參數化類型),List里的String稱為實際參數類型
    • 具體化泛型中的類型時,可以使用 ? extends 或 ? super來表示繼承關系;如List,而里面的 ? 稱為通配符類型WildcardType
    • GenericArrayType 表示一種元素類型是ParameterizedType(參數化類型)或者TypeVariable(類型變量)的數組類型,如T[] 或者 List[]
  • 注解是JDK1.5才出現了的,為了表示被注解的類型的,加入AnnotatedElement類型,字面意思就是被注解的元素。JDK1.8又有了AnnotatedType將Type和被注解元素的概念關聯起來。
  • AnnotatedType也有四個子接口,和Type的四個子接口一一對應,如:ParameterizedType類型被注解則被編譯器解析成AnnotatedParameterizedType: @AnTest("list")Listlist

2 泛型的概念

  • Java 泛型(generics)是JDK1.5中引入的一個新特性,其本質是參數化類型,解決不確定具體對象類型的問題;其所操作的數據類型被指定為一個參數(type parameter)這種參數類型可以用在類、接口和方法的創建中,分別稱為泛型類、泛型接口、泛型方法

泛型: 把類型明確的工作推遲到創建對象或調用方法的時候才去明確的特殊的類型

3 泛型類和泛型方法的示例

  • 泛型類的定義
  1. public class MainTest<T> { 
  2.     private  T param; 
  3. public static void main(String[] args){ 
  4.         MainTest<String> data = new MainTest<String>(){}; 
  5.         ParameterizedType genType1 = (ParameterizedType)data.getClass().getGenericSuperclass(); 
  6.   } 
  • 泛型方法的定義
  1. public class MainTest{ 
  2.     public static void main(String[] args){ 
  3.         printData("siting"); 
  4.     } 
  5.     static  <T> T printData(T t){ 
  6.         System.out.println(t); 
  7.         return t; 
  8.     } 

接口和抽象類都可以使用泛型

4 類型擦除

  • 創建泛型的實例時,jvm是會把具體類型擦除的;編譯生成的字節碼中不包含泛型中的類型參數,即ArrayList和ArrayList都擦除成了ArrayList,也就是被擦除成"原生類型",這就是泛型擦除
  1. public class MainTest { 
  2.     public static void main(String[] args){ 
  3.         List<String> strArr  = new ArrayList<>(); 
  4.         List<Integer> intArr  = new ArrayList<>(); 
  5.         Type strClazz = strArr.getClass(); 
  6.         Type intClazz = intArr.getClass(); 
  7.     } 

  • 查看編譯后的字節碼文件是如何表示的: idea菜單 -> view -> show ByteCode
  1. public class MainTest<T> { 
  2.     T param; 
  3.     public static void main(String[] args){ 
  4.         MainTest<String> test = new MainTest<>(); 
  5.         test.setParam("siting"); 
  6.     } 
  7.     public T getParam() {  return param;   } 
  8.     public void setParam(T param) {  this.param = param;  } 
  9. public class com/MainTest { 
  10.   ...省略 
  11.   public static main([Ljava/lang/String;)V 
  12.    L0 
  13.     LINENUMBER 7 L0 
  14.     NEW com/MainTest 
  15.     DUP 
  16.     INVOKESPECIAL com/MainTest.<init> ()V 
  17.     ASTORE 1 
  18.    L1 
  19.     LINENUMBER 8 L1 
  20.     ALOAD 1 
  21.     LDC "siting"     // 調用類型擦除后的setParam(Object) 
  22.     INVOKEVIRTUAL com/MainTest.setParam (Ljava/lang/Object;)V 
  23.    L2 
  24.    ...省略//getParam 的返回值是Object 
  25.   public getParam()Ljava/lang/Object; 
  26.    L0 
  27.     LINENUMBER 10 L0 
  28.     ALOAD 0 
  29.     GETFIELD com/MainTest.param : Ljava/lang/Object; 
  30.     ARETURN 
  31.    ...省略//setParam 的入參是Object 
  32.   public setParam(Ljava/lang/Object;)V 
  33.    L0 
  34.     LINENUMBER 11 L0 
  35.     ALOAD 0 
  36.     ALOAD 1 
  37.     PUTFIELD com/MainTest.param : Ljava/lang/Object; 
  38.     RETURN 
  39.    ... 

可以看出T(String)都被轉換為Object類型,最初的初始化的String不見了

5 泛型的繼承

  • 子類可以指定父類的泛型參數,可以是已知類(Integer、String等),也可以用子類自己的泛型參數指定
  • 泛型被繼承時,且指定父類泛型參數,則額外生成的ParameterizedType類型作為子類的父類;如果沒有指定父類泛型參數,則直接繼承原生類型
  1. public class MainTest<T> { 
  2.     T param; 
  3.     static public class SubTest1 extends MainTest<String>{} 
  4.     static public class SubTest2<R> extends MainTest<R>{} 
  5.     //SubTest3繼承的時原生類型 
  6.     static public class SubTest3 extends MainTest{} 

6 泛型變量TypeVariable

  • (先臨時定義一個名稱,Test里的E為泛型參數);泛型變量TypeVariable:泛型的泛型參數就是TypeVariable;當父類使用子類的泛型參數指定自身的泛型參數時;或者泛型屬性定義在泛型類A中,并使用泛型類A的泛型參數T時,其泛型參數都會被編譯器定為泛型變量TypeVariable,而不是被擦除
  1. public class MainTest<T> { 
  2.     List<T> param; 
  3.     public static void main(String[] args) throws Exception{ 
  4.         Class clazz =  MainTest.class; 
  5.         TypeVariable[] typeVariable = clazz.getTypeParameters(); 
  6.         // 1 
  7.         Field field = clazz.getDeclaredField("param"); 
  8.         ParameterizedType arrayType = (ParameterizedType)field.getGenericType(); 
  9.         // interface List<E> 的泛型類型E被T,具體化,因此其被識別為 TypeVariable 
  10.         TypeVariable variable1 = (TypeVariable)arrayType.getActualTypeArguments()[0]; 
  11.         // 2 
  12.         ParameterizedType type = (ParameterizedType)SubTest.class.getGenericSuperclass(); 
  13.         TypeVariable variable2 = (TypeVariable)type.getActualTypeArguments()[0]; 
  14.     } 
  15.     static class SubTest<R> extends MainTest<R>{} 

7 參數化類型ParameterizedType

  1. public interface ParameterizedType extends Type { 
  2.     //獲取實際參數,List<String>里的String; 如果是List<T>則是TypeVariable類型 
  3.     Type[] getActualTypeArguments();  
  4.     // 獲取原始類型List<String> -> List<E> 
  5.     Type getRawType();   
  6.     Type getOwnerType(); 
  • 需要注意的點,我們不能直接獲取指定具體參數的泛型的類型,如Class clazz = List.class編譯時不通過的;還有就是直接通過泛型類new創建的對象,其Class并非ParameterizedType類型,而是泛型本身的class,示例如下
  1. public class MainTest<T> { 
  2.     public static void main(String[] args){ 
  3.         MainTest<String> str = new MainTest<String>(); 
  4.         Class variable = str.getClass(); 
  5.         Type genType1 = variable.getGenericSuperclass(); 
  6.     } 

  • 被具體參數化的泛型才能被編譯器識別為ParameterizedType類型,有三種方式獲取ParameterizedType類型
  1. // 1 子類繼承泛型時,指定具體參數(可以是String等已知類型,也可以是子類的泛型參數) 
  2. // 2 獲取在類內部定義的泛型屬性,需指定具體泛型參數 
  3. // 3 局部代碼,可以通過泛型的匿名內部子類(需指定具體泛型參數)獲取ParameterizedType類型 
  4. public class MainTest<T> { 
  5.     List<T> list; 
  6.     public static void main(String[] args) throws NoSuchFieldException { 
  7.         SubTest<String> str = new SubTest<>(); 
  8.         // 方式一 
  9.         Class variable = str.getClass(); 
  10.         // 父類是(521)ParameterizedType類型 
  11.         ParameterizedType genType = (ParameterizedType)variable.getGenericSuperclass(); 
  12.         // (521)ParameterizedType類型的原生類型是(479)class com.MainTest 
  13.         Type clazz = genType.getRawType(); 
  14.         //MainTest.class 的原生類型是 (479)class com.MainTest 
  15.         Class rawClazz = MainTest.class; 
  16.  
  17.         //方式二,泛型屬性 
  18.         Field field = rawClazz.getDeclaredField("list"); 
  19.         //屬性list 類型是(546)ParameterizedType類型List<T> 
  20.         ParameterizedType fieldType = (ParameterizedType)field.getGenericType(); 
  21.  
  22.         // 方式三 
  23.         MainTest<String> sub3 = new MainTest<String>(){}; 
  24.         // clazz3是匿名子類 
  25.         Class clazz3 =  sub3.getClass(); 
  26.         //父類是(555)ParameterizedType類型 
  27.         ParameterizedType genType3 = (ParameterizedType) clazz3.getGenericSuperclass(); 
  28.         // (555)ParameterizedType類型的原生類型是(479)class com.MainTest 
  29.         Type type3 = genType3.getRawType(); 
  30.     } 
  31.     public static class SubTest<R> extends MainTest<R>{ } 

8 通配符(WildcardType)

無邊界通配符:無界通配符 ? 可以適配任何引用類型:

  • 當方法參數需要傳入一個泛型時,而且無法確定其類型時。直接使用無具體泛型變量的泛型,容易造成安全隱患;若在方法代碼里進行類型轉換,極容易出現ClassCastException錯誤
  • 那泛型變量用Object代替不就行了?但是泛型類+具體參數轉變的ParameterizedType(參數化類型)是不存在繼承關系;即Object是String的父類,但是List 和List的類型是不同的兩個ParameterizedType,不存在繼承關系。于是有了類型通配符 ?
  1. public static void print(List list){}  
  2. ----->>> 
  3. public static void print(List<?> list){}  

  • 無界通配符可以匹配任意類型;但是在使用?時,不能給泛型類的變量設置值,因為我們不知道具體類型是什么;如果強行設置新值,后面的讀容易出現ClassCastException錯誤。因此編譯器限制了**通配符 ?**的泛型只能讀不能寫

上界限定通配符 < ? extends E>

  • 想接收一個List集合,它只能操作數字類型的元素【Float、Integer、Double、Byte等數字類型都行】,怎么做?可以使用List,表明List里的元素都是Number的子類
    1. public static void print(List<? extends Number> list) { 
    2.         Number n = new Double("1.0"); 
    3.         list.add(n); 
    4.         Number tmp = list.get(0); 
    5.     } 

  • 圖片里可以看出,存在上界通配符,因為具體類型不確定,也是只能讀不能寫的

下界限定通配符 < ? super E>

  1. class Parent{ } 
  2. class Child extends Parent{ } 
  3. public class MainTest<T> { 
  4.     T param; 
  5.     public static void main(String[] args){ 
  6.         MainTest<? super Child> parent_m = new MainTest<>(); 
  7.         parent_m.setParam(new Child()); 
  8.         Object parent = parent_m.getParam(); 
  9.     } 
  10.     public T getParam() {  return param;  } 
  11.     public void setParam(T param) {  this.param = param; } 

  • 如果定義了通配符是誰的父類,則是下界限定通配符;此類通配符可讀可寫,轉成任意父類都不會出現ClassCastException錯誤。
  • 個人猜想:難道是因為通配符和上界限定通配符的泛型 向下轉型容易出現ClassCastException錯誤,而下界限定通配符向上轉型不會出現ClassCastException錯誤,因此java規范限制前者編譯出錯,而后面編譯通過?

9 泛型數組(GenericArrayType)

  1. public interface GenericArrayType extends Type { 
  2.     //獲得這個數組元素類型,即獲得:A<T>(A<T>[])或  T(T[]) 
  3.     Type getGenericComponentType(); 
  • GenericArrayType,泛型數組,描述的是ParameterizedType類型以及TypeVariable類型數組,即形如:Test[][]、T[]等,是GenericArrayType的子接口
  1. public class MainTest<T> { 
  2.     T[] param; 
  3.     public static void main(String[] args) throws Exception{ 
  4.         Class clazz =  MainTest.class; 
  5.         Field field = clazz.getDeclaredField("param"); 
  6.         GenericArrayType arrayType = (GenericArrayType)field.getGenericType(); 
  7.         TypeVariable variable = (TypeVariable) arrayType.getGenericComponentType(); 
  8.     } 

 

責任編輯:武曉燕 來源: 潛行前行
相關推薦

2025-01-24 08:19:57

2025-11-05 03:00:55

2025-03-28 06:01:00

TypeScript泛型開發

2017-11-14 14:41:11

Java泛型IO

2024-10-22 16:59:07

2024-11-05 09:11:09

TypeScript開發者代碼

2019-09-04 00:20:10

JSON泛型擦除

2009-08-24 18:22:05

C# 泛型編程

2009-09-25 10:03:51

Java泛型

2021-05-10 07:38:09

Swift 泛型Tips

2009-08-24 17:07:09

C# 泛型

2011-06-03 08:49:54

Java

2021-12-30 19:34:15

Java泛型JDK

2020-11-10 07:09:59

Java泛型語言

2021-06-17 06:51:32

Java泛型Java編程

2021-09-29 18:17:30

Go泛型語言

2021-07-01 06:47:30

Java泛型泛型擦除

2021-06-18 08:25:42

Java泛型通配符

2011-03-21 16:26:28

java泛型

2016-10-31 19:41:29

Java垃圾回收
點贊
收藏

51CTO技術棧公眾號

正在播放国产一区| 欧美日韩精品| 久久9热精品视频| 午夜免费高清视频| 综合自拍亚洲综合图不卡区| 日本午夜精品| 亚洲精品777| 国产精品一区免费观看| 日韩电影网1区2区| 姬川优奈av一区二区在线电影| 久久天堂久久| 红桃视频国产精品| 日本久久电影网| 91中文字幕在线观看| 导航福利在线| 91精品一区国产高清在线gif| 亚洲久草在线视频| 国产精品999| 在线国产三级| 欧美在线免费| 91麻豆精品国产自产在线 | 久久69国产一区二区蜜臀| 色在人av网站天堂精品| 日本免费高清不卡| 日韩男女性生活视频| 一区二区三区在线视频播放| 欧美色蜜桃97| 怡红院亚洲色图| 亚洲毛片在线观看.| 亚洲图片欧洲图片日韩av| av影院在线| 极品少妇xxxx精品少妇| 精品亚洲国产成av人片传媒 | 九色蝌蚪在线| 久久性天堂网| 伊人亚洲福利一区二区三区| 国产一级特黄a大片免费| 国产福利不卡视频| 久久视频免费观看| 1069男同网址| 小小影院久久| 欧洲成人在线视频| 在线免费观看黄色av| 老鸭窝毛片一区二区三区| 亚洲免费成人av电影| 羞羞电影在线观看www| 国产69精品久久777的优势| 欧美日本高清视频| 欧洲成人一区| 亚洲高清免费视频| 日韩精品大片| 麻豆精品久久| 不卡中文字幕av| 成人黄色av网址| 色久综合一二码| 天堂在线免费av| 国产成人亚洲精品狼色在线| 只有这里有精品| 久久成人高清| 欧美电影精品一区二区| 免费成人在线视频网站| 欧美激情国产在线| 亚洲成av人片在线观看香蕉| 成人中文字幕在线播放| 国产在线精品一区在线观看麻豆| 欧美激情视频给我| av在线资源网| 久久免费电影网| 亚洲精品女av网站| 韩国欧美一区| 亚洲mv在线看| 欧美在线免费看视频| 国产精品自拍视频| 免费观看成人性生生活片 | 石原莉奈在线亚洲二区| 亚洲视频小说| 久久久蜜桃精品| 蜜桃传媒视频麻豆一区| 性欧美lx╳lx╳| 亚洲性生活视频| 美女做暖暖视频免费在线观看全部网址91 | aa级大片欧美三级| 欧美日韩成人精品| 嫩草一区二区三区| 国产三级精品在线不卡| 你懂的在线观看一区二区| 国产精品人成电影| 亚洲青青久久| 精品久久国产字幕高潮| 中文字幕在线一二| 久久免费午夜影院| 一本到av在线| 日韩精品在线视频观看| 要久久电视剧全集免费| 色婷婷综合成人av| 久草在线资源站资源站| 欧美日韩国产一区在线| 成人黄色免费电影| 91日韩精品一区| 91视频成人免费| 久久久精品五月天| 国产三级日本三级在线播放| 国产麻豆欧美日韩一区| 精品亚洲第一| 欧美日韩三级电影在线| 91精品国产毛片武则天| 精品动漫一区二区| 好男人看片在线观看免费观看国语| 成人少妇影院yyyy| 伊人天天久久大香线蕉av色| 欧美成人国产| 国产精品裸体瑜伽视频| 国产一区二区三区免费| 欧美变态视频| 亚洲综合精品久久| 自拍偷拍精选| 亚洲激情自拍图| 超免费在线视频| 精品国产伦一区二区三区免费| 里番在线观看网站| 欧美日韩一级二级| 国产露出视频在线观看| 亚洲va中文字幕| 成人动漫av| 中文综合在线观看| 久久精品青草| 先锋在线亚洲| 久久精品国产亚洲精品| 欧美国产亚洲精品| 欧美一区1区三区3区公司| 亚洲一区二区三区精品在线| 中日韩一区二区三区| 久久精彩免费视频| 欧美aaaaaa午夜精品| 亚洲小说欧美另类激情| 在线国产亚洲欧美| 欧美草逼视频| 91国产在线播放| 亚洲女同在线| 伊人色综合影院| 一本色道亚洲精品aⅴ| 最新97超碰在线| 国产成人精品免费久久久久 | 国产精品久久久久久久久久久久久久 | 亚洲毛片在线免费| 亚洲一区在线免费| 欧美日本在线播放| 九色porny在线| 91在线视频免费| 一区二区三区四区不卡在线| 超碰97久久| 国产三级三级三级看三级| 欧美成人免费视频| 日韩一区自拍| 欧美成人在线免费观看| 国产精品主播直播| а_天堂中文在线| 视频一区不卡| 精品国产欧美一区二区| 日韩成人免费在线| 色爱综合区网| 一区二区精品国产| 国产一区二区三区视频| 成人av网在线| 嫩草懂你的影院| 欧美日韩一区国产| 日韩理论电影大全| 免费黄色在线视频网站| 国产乱码一区| 精品国产露脸精彩对白| 国产精品影音先锋| 国产 日韩 欧美| 亚洲综合色av| 福利视频一区二区| 亚洲成人免费| 成人午夜在线影视| 欧美激情videos| 国产精品三级av| 色棕色天天综合网| 一区二区在线视频观看| 亚洲青青久久| 亚洲精品中文综合第一页| 欧美巨大xxxx| 91久久精品无嫩草影院| 美女精品在线| 美女爽到高潮91| 国产成人午夜视频| 亚洲精品一区二区三区在线观看 | 欧美色视频日本版| 9国产精品午夜| 色狮一区二区三区四区视频| 亚洲欧美视频| 99免费精品在线观看| 中文字幕综合| 国产精品一区二区三区www| 亚洲在线观看| 成人激情黄色小说| 亚洲激情校园春色| aaa欧美日韩| 麻豆专区一区二区三区四区五区|