博客已轉(zhuǎn)到HuJinPu 's blog

          http://blog.csdn.net/hujinpu

          首頁(yè) 新隨筆 聯(lián)系 聚合 管理
            24 Posts :: 0 Stories :: 25 Comments :: 0 Trackbacks

          大家先看看下面這段小程序

          import ?java.util.ArrayList;
          import ?java.util.List;

          // 申明一個(gè)泛型類(lèi)
          public ? class ?GenericClass? {
          ????
          ????
          public ? static ? void ?main(String?[]?args)? {
          ????????List
          < Integer > ?list? = ? new ?ArrayList < Integer > ();
          ????????list.add(
          1 );
          ????????list.add(
          2 );
          ????????
          new ?Product().prt(list);
          ????}

          }


          // 制造一個(gè)類(lèi)用于說(shuō)明問(wèn)題
          class ?Product ? {
          ????
          public ? void ?prt(List < String > ?lt)? {
          ????????System.out.println(lt);
          ????}

          }


          ?

          編譯器報(bào)錯(cuò),說(shuō)無(wú)法將Product中的prt(java.util.List<java.lang.String>)應(yīng)用于(java.util.List<java.lang.Integer>)。前面定義了List<Integer> list = new ArrayList<Integer>();后面卻調(diào)用 public void prt(List<String> lt)用list做參數(shù),肯定是錯(cuò)誤的用法。編譯器報(bào)錯(cuò)的行為是很正確的,他幫助你避免了潛在錯(cuò)誤的發(fā)生。這里要注意泛型的作用:List<Integer>和List<String>雖然看著都是List,但編譯器把他們當(dāng)作不同的class,不能相互替代。這是泛型的基本原則。你可以把他們看成一個(gè)是Class1, 一個(gè)是Class2, 當(dāng)然不能給一個(gè)需要類(lèi)型為Class1的參數(shù)的方法傳一個(gè)類(lèi)型為Class2的參數(shù)的方法啦。

          再來(lái)看上面程序稍微改動(dòng)一處的情況

          import ?java.util.ArrayList;
          import ?java.util.List;

          // 申明一個(gè)泛型類(lèi)
          public ? class ?GenericClass? {
          ????
          ????
          public ? static ? void ?main(String?[]?args)? {
          ????????List
          < Integer > ?list? = ? new ?ArrayList < Integer > ();
          ????????list.add(
          1 );
          ????????list.add(
          2 );
          ????????
          new ?Product().prt(list);
          ????}

          }


          // 制造一個(gè)類(lèi)用于說(shuō)明問(wèn)題
          class ?Product < T > ? {
          ????
          public ? void ?prt(List < String > ?lt)? {
          ????????System.out.println(lt);
          ????}

          }


          編譯器說(shuō)使用了未經(jīng)檢查或不安全的操作,但能編譯通過(guò)并運(yùn)行顯示 [1, 2]。

          這又是為什么呢?就是紅色的那一個(gè)<T>就變化這么大嗎?似乎不是和剛才效果應(yīng)該一樣拉,怎么這回又可以了?

          原因是這樣的:第次程序里面,只是把class Product改成了class Product<T>,盡管類(lèi)型T在Product的代碼里壓根從沒(méi)用到,但是這個(gè)定義把一個(gè)普通類(lèi)(class)變成了原始類(lèi)型(raw class)。generic class Product<T>在JVM運(yùn)行時(shí)是不存在的,Product這個(gè)原始類(lèi)型不是類(lèi)型安全的。因?yàn)樵趎ew Product.prt(list)里面,使用的是原始類(lèi)型的Product,所以里面的list也會(huì)被擦拭成原始類(lèi)型的,所以類(lèi)型就符合了,不會(huì)有編譯錯(cuò)誤而可以運(yùn)行。

          雖然這個(gè)時(shí)候程序盡管可以運(yùn)行,但其使用泛型的方法,無(wú)疑是錯(cuò)誤的。 在這里我只是想和大家分析一些泛型的細(xì)節(jié)問(wèn)題。要大家通過(guò)這個(gè)細(xì)節(jié)明白泛型的細(xì)節(jié)之處(檫試,原始類(lèi)型)。具體的內(nèi)容我就不在說(shuō)了,很多書(shū)都有。推薦java參考大全5edition page264 和 core Java I 7edition Chapter 13. Generic Programming??

          posted on 2006-08-28 16:19 livahu 閱讀(1662) 評(píng)論(5)  編輯  收藏 所屬分類(lèi): Java

          Feedback

          # re: 關(guān)于jdk1.5泛型的思考 2006-08-28 17:17 海藍(lán)
          @livahu
          你在原因部分說(shuō)的內(nèi)容我看不懂啊,感覺(jué)你說(shuō)的原因和結(jié)果之間似乎沒(méi)什么必然的聯(lián)系,可以再整理一下嗎?  回復(fù)  更多評(píng)論
            

          # re: 關(guān)于jdk1.5泛型的思考 2006-08-28 18:29 路人甲
          這個(gè)問(wèn)題我想的確是作者沒(méi)有說(shuō)清楚。不過(guò)只要親自用編譯器試一下應(yīng)該就可以很容易理解了。這里斗膽幫作者稍微深入地解釋一下,如果說(shuō)錯(cuò)了還請(qǐng)不吝賜教,但愿不會(huì)誤人子弟。

          首先,第一段程序里面,前面定義了List<Integer> list = new ArrayList<Integer>();
          后面卻調(diào)用void prt(List<String> l)用list做參數(shù),肯定是錯(cuò)誤的用法。編譯器報(bào)錯(cuò)的行為是很正確的,他幫助你避免了潛在錯(cuò)誤的發(fā)生。

          這里要注意泛型的作用。List<Integer>和List<String>雖然看著都是List,但編譯器把他們當(dāng)作不同的class,不能相互替代。這是泛型的基本原則。你可以把他們看成一個(gè)是Class1, 一個(gè)是Class2, 當(dāng)然不能給一個(gè)需要類(lèi)型為Class1的參數(shù)的方法傳一個(gè)類(lèi)型為Class2的參數(shù)的方法啦。

          而第二段程序里面,只是把class Product改成了class Product <T>,盡管類(lèi)型T在Product的代碼里壓根從沒(méi)用到,只是這個(gè)定義把一個(gè)普通類(lèi)(class)變成了原始類(lèi)型(raw class)。其實(shí)可以自己試一下,一旦把Fangxin.main()里面的new Product().prt(list) 改成了new Product<Integer>().prt(list), (這里面的Integer可以換成任何一個(gè)合法的類(lèi)),那么warning沒(méi)有了,原來(lái)的error又回來(lái)了。

          也就是說(shuō),一旦把Product定義成了原始類(lèi)型,那么在使用這個(gè)class的時(shí)候也就應(yīng)該使用Product<T>的形式,否則的話(huà),編譯器會(huì)認(rèn)為你的行為不正?;蚴呛芪kU(xiǎn),所以給你一個(gè)warning(也許你只是忘了寫(xiě)呢)。正像作者原文里寫(xiě)道的:

          generic class Product<T>在JVM運(yùn)行時(shí)是不存在的,Product叫原始類(lèi)型,原始類(lèi)型不是類(lèi)型安全的.這個(gè)在編譯時(shí)是檢測(cè)不出的,運(yùn)行時(shí)才報(bào)錯(cuò).
          (這里其實(shí)不會(huì)報(bào)錯(cuò),只是因?yàn)榭赡軙?huì)報(bào)錯(cuò),所以編譯器給你一個(gè)warning)。

          而當(dāng)一個(gè)generic class使用原始類(lèi)型時(shí),其方法里的參數(shù)也就相應(yīng)的使用了原始形態(tài),如此列的java.util.List而不是java.util.List<String>
          固new Product().prt(lt)時(shí)可以運(yùn)行.

          (這句是說(shuō),因?yàn)樵趎ew Product.prt(list)里面,你使用的是原始類(lèi)型的Product,所以里面的list也是原始類(lèi)型的,所以類(lèi)型就符合了,不會(huì)有編譯錯(cuò)誤而可以運(yùn)行)。

          但是這個(gè)時(shí)候盡管可以運(yùn)行,但程序的邏輯,至少其使用泛型的方法,無(wú)疑是錯(cuò)誤的。

          個(gè)人認(rèn)為這個(gè)程序應(yīng)該改成這樣才是正確地使用泛型編程的方式:

          import java.util.ArrayList;
          import java.util.List;

          public class Fangxin {

          public static void main(String [] args) {
          List<Integer> list = new ArrayList<Integer>();
          list.add(1);
          list.add(2);
          new Product<Integer>().prt(list);
          }

          }

          class Product<T> {
          public void prt(List<T> l) {
          System.out.println(l);
          }
          }

          最后加一句,編譯器給出error和warning不是故意跟你作對(duì),給你添麻煩,而是為你寫(xiě)出正確的程序提出最好的幫助。所以應(yīng)該盡量讓程序沒(méi)有任何編譯錯(cuò)誤(這個(gè)自然)和警告才是正途。  回復(fù)  更多評(píng)論
            

          # re: 關(guān)于jdk1.5泛型的思考 2006-08-28 20:52 livahu
          很感謝路人甲的指正,我確實(shí)沒(méi)有表達(dá)清楚我的想法,我想通過(guò)路人甲的指正,大家應(yīng)該明白了泛型的細(xì)節(jié)之處,這里的帶有明顯錯(cuò)誤和警告的程序不是要大家去模仿,而是要大家通過(guò)這個(gè)細(xì)節(jié)明白泛型的細(xì)節(jié)之處(檫試,原始類(lèi)型).具體的內(nèi)容我就不在說(shuō)了,很多書(shū)都有,推薦java參考大全5edition page264 和 core Java I 7edition Chapter 13. Generic Programming  回復(fù)  更多評(píng)論
            

          # re: 關(guān)于jdk1.5泛型的思考 2006-08-29 09:00 Dedian
          good article, just for supplement:

          http://www.aygfsteel.com/dedian/archive/2006/06/23/54615.html  回復(fù)  更多評(píng)論
            

          # re: 關(guān)于jdk1.5泛型的思考 2006-09-01 10:16 Spike Wang
          這樣的用法1.5以后才有,最好不要亂用泛型。

          我建議如果是新項(xiàng)目使用無(wú)所謂。

          如果是和以前系統(tǒng)協(xié)作那么最好避免。

          免得給自己找麻煩。

          在泛型還么大量使用的時(shí)候,盡量避免使用。

            回復(fù)  更多評(píng)論
            

          主站蜘蛛池模板: 酒泉市| 浦北县| 牙克石市| 湾仔区| 阿拉尔市| 嘉善县| 昂仁县| 黄石市| 留坝县| 宁阳县| 榆林市| 靖江市| 仙居县| 黄石市| 建宁县| 沙坪坝区| 政和县| 南木林县| 江城| 上杭县| 利津县| 瑞金市| 庆安县| 屏山县| 榕江县| 原阳县| 三亚市| 嘉定区| 芜湖县| 固阳县| 镇原县| 上虞市| 平利县| 新巴尔虎右旗| 洞头县| 德庆县| 五常市| 昭觉县| 精河县| 凤城市| 唐山市|