隨筆-67  評論-522  文章-0  trackbacks-0
              前一篇對泛型進行了一番總結(jié),本篇就來說說與泛型有關(guān)的反射。
              我在泛型篇中說到了泛型在JVM中是會被擦除的,不過擦除的類還是“殘留”了一些泛型的痕跡。比如Person<T>類,雖然擦除掉了泛型<T>,但是通過反射機制是可以獲得這些信息的,不光如此,Person類里面定義的泛型方法都可以通過反射獲得。讓我們用代碼來驗證一下。
              在用代碼驗證之前,大象會對Person類稍微改造一下,增加一個泛型變量K以及一個泛型方法,其它的都保持不變。
              public class Person<T, K extends Comparable<? super T> & Serializable>
                  extends SuperPerson<String> implements Handle<Date> {
                  ......
                  public static <T extends Comparable<? super T>> T max(List<? extends T> list){
                    Iterator<? extends T> it = list.iterator();
                      T result = it.next();
                      while(it.hasNext()){
                          T t = it.next();
                          if(t.compareTo(result) > 0)
                              result = t;
                      }
                      return result;
                  }
                  ......
              }
              下面可以開始寫代碼了嗎?別急,大象還想先把代碼中用到的幾個跟反射有關(guān)的API接口說明一下,這都是JDK5.0中為泛型新增的,然后還用到了一個JDK6.0提供的Modifier,它是一個枚舉類型,可以表示類、方法或字段的修飾符。
              Type
              它是所有類型的公共接口。包括原始類型、參數(shù)化類型、數(shù)組類型、類型變量和基本類型。ParameterizedType, TypeVariable, WildcardType,GenericArrayType這四個接口都是它的子接口。
              GenericDeclaration
              這個接口ClassMethodConstructor都有實現(xiàn),我們就是要用這個接口的getTypeParameters方法,它返回一個TypeVariable[]數(shù)組,這個數(shù)組里面就是我們定義的類型變量TK,順序與我們聲明時一樣。如果用循環(huán)語句將數(shù)組打印出來,你會發(fā)現(xiàn)只會輸出TK,這可不是我們想要的結(jié)果,那么想要獲得預(yù)期的結(jié)果怎么辦呢?請繼續(xù)往下看。
              TypeVariable
              它表示類型變量。比如T,比如K extends Comparable<? super T> & Serializable,這個接口里面有個getBounds()方法,它用來獲得類型變量上限的Type數(shù)組,如果沒有定義上限,則默認設(shè)定上限為Object,請注意TypeVariable是接口,實際得到的是TypeVariableImpl實現(xiàn)類,下面幾個接口都一樣。
              TK來說明,T沒有定義任何上限,所以它就有一個默認上限java.lang.Object,實際跟蹤代碼的時候你會發(fā)現(xiàn)Tbounds屬性為空,只有在調(diào)用了getBounds()方法后,才會有一個Type[1]數(shù)組[class java.lang.Object]。而對于K來說,調(diào)用了getBounds方法后,得到的數(shù)組是[java.lang.Comparable<? super T>, interface java.io.Serializable],它們的類型卻是不一樣的,第1個是ParameterizedType,而第二個是Class
              ParameterizedType
              ParameterizedType表示參數(shù)化類型,就是上面說的java.lang.Comparable<? super T>,再比如List<T>List<String>,這些都叫參數(shù)化類型。得到Comparable<? super T>之后,再調(diào)用getRawType()getActualTypeArguments()兩個方法,就可以得到聲明此參數(shù)化類型的類(java.lang.Comparable)和實際的類型參數(shù)數(shù)組([? super T]),而這個? super T又是一個WildcardType類型。
              WildcardType
              它用來描述通配符表達式,上面返回的? super T正好是這個類型。然后調(diào)用getUpperBounds()上限和getLowerBounds()下限這兩個方法,獲得類型變量?的限定類型(上下限),對于本例的通配符(?),它的上限為java.lang.Object,下限為T
          通過上面幾個接口的分析,可以將Person類的泛型參數(shù)都解析出來,那么Person的超類以及實現(xiàn)的接口該怎么處理呢?Class類里面同樣在1.5版本加入了getGenericSuperclass()getGenericInterfaces()兩個方法,用于返回帶參數(shù)化類型的超類與接口。
              至此,通過上面這些接口和方法我們已經(jīng)可以把class Person后面的代碼都解析出來了,類里面的方法與解析類的泛型化參數(shù)類似,就不再贅述了。下圖就是通過反射將定義的Person類打印出來的結(jié)果。
              
              本文主要是想通過反射機制來驗證在JVM虛擬機中獲得泛型的一些知識。一般實際使用的時候多數(shù)是通過反射獲取超類的泛型,或者通過反射調(diào)用方法,讀取/設(shè)置屬性值等等這些功能,最下面有示例源碼的下載。
              反射雖然很有用處,但也不能濫用。首先用了反射就沒辦法在編譯時進行類型檢查,而且反射的代碼比較復(fù)雜不容易閱讀,不過好在現(xiàn)在有很多已經(jīng)封裝好的反射工具類,幫我們做了不少這方面的工作。最后也是最重要的一點是因為,使用反射會有一定的性能損耗,就是說會比直接調(diào)用方法要慢,至于慢多少,這個不好說,但肯定會慢,因此除非有必要,大象建議在一般情況下首先考慮用接口來代替反射。
              以上這些都是本篇關(guān)于泛型相關(guān)的反射介紹,算是一個入門知識吧,有什么不對的,或不完善的地方,還請各位指出來,謝謝!
              源碼下載: 泛型與反射 
              本文為菠蘿大象原創(chuàng),如要轉(zhuǎn)載請注明出處。http://www.aygfsteel.com/bolo
          posted on 2014-05-06 14:33 菠蘿大象 閱讀(6147) 評論(1)  編輯  收藏 所屬分類: Java

          評論:
          # re: 泛型與反射的使用總結(jié)之反射篇 2014-05-23 15:45 | 王凱文
          略難 有點不太懂.  回復(fù)  更多評論
            
          主站蜘蛛池模板: 楚雄市| 井研县| 安阳市| 马山县| 凤凰县| 兴安盟| 天峨县| 十堰市| 南江县| 韩城市| 丹寨县| 安顺市| 卢龙县| 四子王旗| 吉安市| 通榆县| 南宫市| 溧水县| 昭苏县| 涪陵区| 牡丹江市| 建平县| 格尔木市| 徐闻县| 濉溪县| 兰西县| 昭平县| 翼城县| 沾化县| 固原市| 南阳市| 紫云| 建昌县| 天门市| 韩城市| 滁州市| 新兴县| 桂林市| 茶陵县| 泰宁县| 漠河县|