Tin's Blog

          You are coming a long way, baby~Thinking, feeling, memory...

            BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            128 隨筆 :: 0 文章 :: 221 評(píng)論 :: 0 Trackbacks

          江南白衣的Blog上一篇:
          Java5泛型的用法,T.class的獲取和為擦拭法站臺(tái)
          他參考的這里:
          Generic Data Access Objects

          我們的項(xiàng)目中也用的GenericHibernateDAO,里面使用了一個(gè):

          public ?GenericHibernateDAO( final ?Class < E > ?clazz)?{
          ????????
          this .clazz? = ?clazz;
          ????}

          的構(gòu)造函數(shù)。
          但是看了江南白衣的介紹,的確方便的可以寫(xiě)成:
          public?GenericHibernateDAO()?{
          ????????
          this.clazz?=?(Class<E>)?((ParameterizedType)?getClass()
          ?????????????????????????????????????????????????????????.getGenericSuperclass()).getActualTypeArguments()[
          0];
          ????}
          這樣,繼承的子DAO就可以不用寫(xiě)Super(xxx.class)進(jìn)行構(gòu)造了。

          其中的:
          (Class<E>)?((ParameterizedType)?getClass().getGenericSuperclass()).getActualTypeArguments()[0];?
          非常神奇,看了faint的一個(gè)回復(fù)(請(qǐng)參照白衣的Blog):
          package?test;?

          import?java.lang.reflect.ParameterizedType;?
          import?java.lang.reflect.Type;?

          import?junit.framework.TestCase;?

          class?TClass<T>?{?
          }?

          class?GoodClass<T>?extends?TClass<String>?{?
          public?ParameterizedType?getClassT()?{?
          return?(ParameterizedType)?getClass().getGenericSuperclass();?
          }?
          }?

          class?BadClass<T>?extends?TClass<T>?{?
          public?ParameterizedType?getClassT()?{?
          return?(ParameterizedType)?getClass().getGenericSuperclass();?
          }?
          }?

          public?class?GenericsTest?extends?TestCase?{?

          private?void?print(Type[]?targs)?{?
          System.out.print(
          "actual?type?arguments?are:");?
          for?(int?j?=?0;?j?<?targs.length;?j++)?{?
          System.out.print(
          "?instance?of?"?+?targs[j].getClass().getName()?+?":");?
          System.out.println(
          "?("?+?targs[j]?+?")");?
          }?
          }?

          public?void?testGoodClass()?throws?Exception?{?
          ParameterizedType?type?
          =?new?GoodClass<String>().getClassT();?
          Type[]?types?
          =?type.getActualTypeArguments();?
          print(types);?

          assertEquals(TClass.
          class,?type.getRawType());?
          assertEquals(String.
          class,?types[0]);?
          }?

          public?void?testBadClass()?throws?Exception?{?
          ParameterizedType?type?
          =?new?BadClass<String>().getClassT();?
          Type[]?types?
          =?type.getActualTypeArguments();?
          print(types);?

          assertEquals(TClass.
          class,?type.getRawType());?
          assertEquals(String.
          class,?types[0]);?
          }?
          }
          例子中的 BadClass 非常有意思,無(wú)法獲取T的實(shí)際類型,我試驗(yàn)了半天也得不到。
          看到也有朋友問(wèn)這個(gè)問(wèn)題:
          http://forum.java.sun.com/thread.jspa?threadID=684429&messageID=3985573

          納悶,怎么就不行呢。
          翻了翻候捷的這篇文章:http://www.jjhou.com/javatwo-2004-GP-in-jdk15.pdf
          才恍然大悟,原來(lái)對(duì)于BadClass這種情況就是獲取不了它的Class。

          這是擦拭法的本意。
          實(shí)際上BadClass<String>()實(shí)例化以后Class里面就不包括T的信息了,對(duì)于Class而言T已經(jīng)被擦拭為Object。而真正的T參數(shù)被轉(zhuǎn)到使用T的方法(或者變量聲明或者其它使用T的地方)里面(如果沒(méi)有那就沒(méi)有存根,這里指ParameterizedTyp),所以無(wú)法反射到T的具體類別,也就無(wú)法得到T.class。
          而getGenericSuperclass()是Generic繼承的特例,對(duì)于這種情況子類會(huì)保存父類的Generic參數(shù)類型,返回一個(gè)ParameterizedType,這時(shí)可以獲取到父類的T.class了,這也正是子類確定應(yīng)該繼承什么T的方法。
          我們應(yīng)該利用這種特性,這對(duì)實(shí)現(xiàn)模版方法非常有用。
          posted on 2006-05-08 21:37 Tin 閱讀(2589) 評(píng)論(3)  編輯  收藏 所屬分類: Other Project

          評(píng)論

          # re: 范型擦拭法即范型類無(wú)法獲取范型參數(shù)信息的原因 2006-05-28 21:25 差沙
          哦,這么說(shuō)來(lái)faint的例子其實(shí)使用了一個(gè)障眼法。其實(shí)GoodClass里面的String跟new GoodClass<String>中的String沒(méi)有任何關(guān)系。

          getGenericSuperclass取到的也是extend 時(shí)候的String。  回復(fù)  更多評(píng)論
            

          # re: 范型擦拭法即范型類無(wú)法獲取范型參數(shù)信息的原因 2006-05-29 16:15 Tin
          恩,我是這么理解的。主要就是因?yàn)榉盒褪蔷幾g期的,運(yùn)行期本應(yīng)該是不可用的。獲取getGenericSuperclass則是特例,此時(shí)由于編譯順序造成不能編譯后馬上擦除T的信息,所以保留了一個(gè)ParameterizedType,所以我們就有幸得到它了。:D  回復(fù)  更多評(píng)論
            

          # re: 范型擦拭法即范型類無(wú)法獲取范型參數(shù)信息的原因 2006-11-08 00:51 江南白衣
          另外有些可以情況可以反射,比如如果是在屬性中定義的泛型

          class BookManager{

          Book<String> book;
          }

          這個(gè)時(shí)候用Field field = BookManager.class.getDeclaredField("book");取得Field
          然后 Type gtype = field.getGenericType();
          if (gtype instanceof ParameterizedType)
          ....同上  回復(fù)  更多評(píng)論
            

          主站蜘蛛池模板: 渑池县| 共和县| 宽城| 富平县| 织金县| 平昌县| 濮阳市| 栾城县| 新乡市| 黄山市| 剑河县| 日土县| 前郭尔| 离岛区| 长兴县| 东源县| 荔波县| 南雄市| 武隆县| 望谟县| 景洪市| 闻喜县| 天气| 庆阳市| 兴安县| 郎溪县| 克什克腾旗| 六安市| 酉阳| 亚东县| 嘉祥县| 霍林郭勒市| 大同市| 钟祥市| 马公市| 时尚| 灵璧县| 蕲春县| 安溪县| 成都市| 宝鸡市|