下載本文檔
版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第10章 泛型是JDK1.5中新加入的元素,它改變了API中的許多類和方法。使用泛型,的強(qiáng)大功能,從根本上改變了Java代碼的編寫(xiě)方式。IntegerIntegermax(Integera,Integerb){returna>b?a:b;}IntegerDoubleFloat類型,那么就需要另外再寫(xiě)max()方法。參數(shù)有多少種類型,就要寫(xiě)多少個(gè)max()方法。但是無(wú)論怎么改變參數(shù)的類型,實(shí)際上max()方法體的代碼并不需要改變。如max()ab的數(shù)據(jù)類型,而等到調(diào)用的時(shí)候再來(lái)確定這兩個(gè)參數(shù)的數(shù)據(jù)類型,那么只需要編寫(xiě)一個(gè)max()就可以了,這將大大在C++中,提供了函數(shù)模板和類模板來(lái)實(shí)現(xiàn)這能。而從JDK1.5開(kāi)始,也提供了C++的模板很相似,但它們是采用完全不同的技在泛型出現(xiàn)之前,Java的程序員可以采用一種變通的辦法:將參數(shù)的類型均為ObjectObject類是所有類的父類,所以它可以指向任何類對(duì)象,但這樣做不能Object與實(shí)【10.1//--------------文件名Generic.java,程序10.1---------- publicclassTobobT,現(xiàn)在不能具體確定它的類型,需要到創(chuàng)建對(duì)象時(shí)才能確定Generic(To){ob=}TgetOb(){return}void}}//--------------文件名demoGeneric.java,程序10.2----------publicpublicclasspublicstaticvoidmain(String 一個(gè)Integer類型的Generic變Generic<Integer>//創(chuàng)建一個(gè)Integer類型的Generic對(duì)iobj=newintk=iobj.getOb(); 一個(gè)String類型的Generic變Generic<String>//創(chuàng)建一個(gè)Double類型的Generic對(duì)sobj=new Strings=sobj.getOb();}}TypeTypeofTis:java.lang.IntegerTypeofT publicclass 其中,TGeneric的實(shí)際類型的占位符。因此,在Generic中,每當(dāng)需要類型參數(shù)時(shí),就會(huì)用到T。注意,T是被括在“<>”中的。每個(gè)被的類型參數(shù),都要放在尖括號(hào)中。由于Generic使用了類型參T T只是一個(gè)占位符,所以ob的實(shí)際類型要由創(chuàng)建對(duì)象時(shí)的參數(shù)傳遞進(jìn)來(lái)。比如,T的類型是StringobString類型。o){ob=}它的參oT。這o的實(shí)際類型,是由創(chuàng)Generic對(duì)象時(shí)傳遞ToobT類型,所以無(wú)論實(shí)際類型是什TTgetOb(){returnob;綜合上面的用法,可以看出,T是一個(gè)數(shù)據(jù)類型的說(shuō)明,它可以用來(lái)說(shuō)明任何實(shí)例方注意:類型參數(shù)T不能使用在靜態(tài)Generic 有對(duì)T的都會(huì)被替換為Integer。所以ob和o都是Integer類型,而且方法getOb()的返回類型也是Integer類型的。Java的編譯器并不會(huì)創(chuàng)建多個(gè)不同版本的Generic類。相反,編譯器會(huì)刪除所有iobjiobj=new所以用new返回的必須是Generic<Integer>類型。無(wú)論是省略Integer,還是將其改成iobjiobjnewGeneric<Double>(1.234錯(cuò)Generic(TGeneric(TJava的自動(dòng)裝箱機(jī)制(12.3節(jié)中介紹)。當(dāng)然,創(chuàng)建對(duì)象也可iobjiobj=newGeneric(newintintk=注意,getObIntegerint變量時(shí),系統(tǒng)會(huì)自動(dòng)拆intintk=后面創(chuàng)建String版本的過(guò)程和前面的完全一樣,在此不再贅述。類型,而不能使用int或char之類的簡(jiǎn)單類型。比如不能這樣寫(xiě):GenericGeneric<intobnewGenericint>(100);//錯(cuò)C++模板的一個(gè)重要//--------------文件名twoGen.java,程序10.3----------publicclasstwoGen<T,V>{TVtwoGen(To1,Vo2){ob1=o1;ob2=}//顯示TV的類voidSystem.out.println("TypeofTis"+ob1.getClass().getName());System.out.println("TypeofVis"+ob2.getClass().getName());getOb1(){returnob1;getOb2(){eturn//--------------文件名simpGen.java,程序10.4----------publicpublicclasspublicstaticvoidargs[]){twoGen<Integer,String>tgObj; tgObj=newtwoGen<Integer,String>(100," intv=tgObj.getOb1();System.out.println("value:"+v);Stringstr=tgObj.getOb2();System.out.println("value:"+str);}TypeTypeofTisjava.lang.IntegerTypeofVisjava.lang.Stringvalue:100 與只有一個(gè)類型參數(shù)的泛型相比,本例并沒(méi)有什么難于理解的地方。Java并沒(méi)有規(guī)定 //--------------文件名Stats.java,程序10.5----------Stats<T>{T[]nums;Stats(Tobj){nums=}average(){doublesum=0.0;for(inti=0;i<nums.length;++i)sum+=returnsum/其中,nums[i].doubleValue()Ingeger、Double等數(shù)據(jù)封裝類轉(zhuǎn)換成雙精度數(shù)后Number類的子類都有這個(gè)方法。但問(wèn)題是,編譯器無(wú)法預(yù)先知道,程序員的意圖是只能使用Number類來(lái)創(chuàng)Stats對(duì)象,因此,編譯時(shí)會(huì)報(bào)告找不到doubleValue()classclassclassname<Textends【10.3//--------------文件名Stats.java,程序10.6----------////下面這個(gè)泛型的實(shí)際類型參數(shù)只能是Number或它的子classStats<TextendsNumber>{T[]nums;Stats(T[]obj){nums=}average(){doublesum=0.0;for(inti=0;i<nums.length;sum+=nums[i].doubleValue(); returnsum/nums.length;}//--------------文件名demoBounds.java,程序10.7----------publicpublicclasspublicstaticvoidmain(Stringargs[]){Integerinums[]=Stats<Integer> iobjnewStats<Integer>(inums);Doublednums[]={1.1,2.2,3.3,4.4,5.5};Stats<Double> dobjnewStats<Double>(dnums);//如果像下面這樣創(chuàng)建String類型的對(duì)象將無(wú)法編譯通//Stringsnums[]=//Stats sobj=new//System.out.println("平均值}classStats<Textends 注意:這里使用的關(guān)鍵字仍然是extends而非implements。classStats<TextendsComparable& 注意:限界類型用“&”分隔,因?yàn)槎禾?hào)用來(lái)分隔類型參數(shù)。在多個(gè)限界中StatsdoSomething()的方法,這個(gè)方法有一個(gè)形式參數(shù),也是Stats類型,如下所示:classclassvoiddoSomething(Statsob){}}IntegerIntegerinums[]=Stats<Integer> iobj=newStats<Integer>(inums);Doublednums[]={1.1,2.2,3.3,4.4,5.5};Stats<Double> dobjnewStats<Double>(dnums);dobj.doSomething(iobj);//錯(cuò)誤 voiddoSomething(Stats<T> voiddoSomething(Stats<U> 使用Java提供的通配符“?”,它的使用形式如下: voiddoSomething(Stats<?> 【10.4//--------------文件名Stats.java,程序10.8----------classclassStats<TextendsNumber>{T[]nums;Stats(T[]obj){nums=}average(){doublesum=0.0;for(inti=0;i<nums.length;++i)sum+=nums[i].doubleValue();returnsum/}voiddoSomething(Statsob){//這里使用了類型通配符}//--------------文件名demoWildcard.java,程序10.9----------publicclassdemoWildcard{publicpublicclassdemoWildcard{publicstaticvoidmain(Stringargs[]){Integerinums[]Stats<Integer> iobj=newStats<Integer>(inums);Doublednums[]={1.1,2.2,3.3,4.4,5.5};Stats<Double> dobj=newStats<Double>(dnums); } voiddoSomething(Stats<?>ob)//這里使用了類型通配 classStats<Textends Stats<?extendsInteger> Stats<?extendsString> IntegerNumberStringNumber的子類。通配符無(wú)法將上界改classStats<?extends 在C++中,除了可以創(chuàng)建模板類,還可以創(chuàng)建模板函數(shù)。在Java中也提供了類似的功能: 權(quán)限修飾符(包括private、public、protected)、static和final都必須寫(xiě)在類 【10.5//--------------文件名demoGenMethods.java,程序10.10----------publicpublicclass//定義泛型方法,有一個(gè)形式參數(shù)用類型參數(shù)T來(lái)定publicstatic<T>voidshowGenMsg(Tob,n){TlocalObobT來(lái)}publicstatic<T>voidob){}publicstaticvoidmain(Stringargs[]){Stringstr="parameter";Integerk=newInteger(123);}型方法相互重載(參數(shù)的個(gè)數(shù)不同)T的使用和泛型類中的使用在第一種調(diào)用形式中,傳入了一個(gè)實(shí)際類型:<Integer>,它表明類型參數(shù)是 public<T>voiddoSomething(){public<T>voiddoSomething(){Tob;}publicclassGeneric<T>{publicpublicclassGeneric<T>{public<U>voidshowGenMsg(Uob){}}publicpublicclassU>{publicvoidshowGenMsg(U}interface接口名<類型參數(shù)表 //--------------文件名MinMax.java,程序10.11----------interfaceinterfaceMinMax<TextendsComparable<T>>{Tmin();Tmax();}T//--------------文件名MyClass.java,程序10.12----------classclassMyClass<TextendsComparable<T>>implementsMinMax<T>{T[]vals;MyClass(Tob){vals=}publicTTval=for(inti=1;i<vals.length;++i)if(vals[i].compareTo(val)<0)val=vals[i];returnval;}publicTTval=for(inti=1;i<vals.length;++i)if(vals[i].compareTo(val)>0)val=vals[i];returnval;}}classclassMyClass<TextendsComparable<T>>implements看上去有點(diǎn)奇怪,它的類型參數(shù)T必須和要實(shí)現(xiàn)的接口中的完全一樣。反而是接口MinMax的類型參數(shù)T最初是寫(xiě)成有界形式的,現(xiàn)在已經(jīng)不再需要重寫(xiě)一遍。如果重寫(xiě)classclassMyClass<TextendsComparable<T>>implementsMinMax<TextendsclassclassMyClassimplementsclassclassMyClassimplements這樣寫(xiě)是正確的,現(xiàn)在這個(gè)類不再是泛型類。編譯器會(huì)在編譯此類時(shí),將類型參數(shù)T 代替,而無(wú)需等到創(chuàng)建對(duì)象時(shí)再處理//--------------文件名demoGenIF.java,程序10.13----------publicpublicclasspublicstaticvoidmain(Stringargs[]){Integerinums[]=Characterchs[]={'x','w','z','y','b','o','p'};MyClass<Integer>iob=newMyClass<Integer>(inums);MyClass<Character>cob=newMyClass<Character>(chs);System.out.println("Maxvalueininums:"+iob.max());System.out.println("Minvalueininums:"+iob.min());System.out.println("Maxvalueinchs:"+cob.max());System.out.println("Minvalueinchs:"+cob.min());}MaxMaxvalueininums:85Minvalueininums:12Maxvalueinchs:zMinvalueinchs:和普通類一樣,泛型類也是可以繼承的,任何一個(gè)泛型類都可以作為父類或子類。不過(guò)泛型類與非泛型類在繼承時(shí)的主要區(qū)別在于:泛型類的子類必須將泛型父類所需要的類型參數(shù),沿著繼承鏈向上傳遞。這與構(gòu)造方法參數(shù)必須沿著繼承鏈向上傳遞的方式類似。以泛型類為父【10.7//--------------文件名superGen.java,程序10.14----------publicpublicclasssuperGen<T定義一個(gè)泛型類Tob;publicsuperGen(Tob){this.ob=ob;}superGen(){ob=publicTpublicTgetOb(){return}//--------------文件名derivedGen.java,程序10.15----------publicclassderivedGen<T>extendssuperGen<T>{publicclassderivedGen<T>extendssuperGen<T>{publicderivedGen(Tob){}}publicclassderivedGen<T>extends 這兩個(gè)類型參數(shù)必須用相同的標(biāo)識(shí)符T。這意味著傳遞給derivedGen的實(shí)際類型也會(huì)傳遞給superGen。例如,下面的定義:derivedGen<Integer>number=new IntegerderivedGensuperGen,因此,后者的成員ob也是Integer類型。雖然derivedGen里面并沒(méi)有使用類型參數(shù)T,但由于它要傳遞類型參數(shù)給父類,所以它不能定義成非泛型類。當(dāng)然,derivedGenT,還可以增加自己需要的類型參數(shù)。下面這個(gè)程序展示了一個(gè)更為復(fù)雜的derivedGen類。//--------------文件名derivedGen.java,程序10.16----------publicpublicclassderivedGen<T,U>extendssuperGen<T>{Udob;publicderivedGen(Tob1,Uob2){super(ob1); 數(shù)給父類dob=ob2; }publicUgetDob(){return//--------------文件名demoHerit_1.java,程序10.17----------publicpublicclasspublicstaticvoidmain(String//創(chuàng)建子類的對(duì)象,它需要傳遞兩個(gè)參數(shù),Integer類型給父類,自己使用String類derivedGen<Integer,String>derivedGen<Integer,String>oa=newderivedGen<Integer,String>(100,"Valueis:");}}ValueValueis:以非泛型類為父【10.8//--------------文件名nonGen.java,程序10.18----------}//--------------文件名derivedNonGen.java,程序10.19----------publicpublicclassderivedNonGen<T>extendsnonGen{Tob;publicderivedNonGen(Tob,intn){super(n);this.ob=}publicTgetOb(){return}//--------------文件名demoHerit_2.java,程序10.20----------publicpublicclasspublicstaticvoidmain(StringderivedNonGen<String>oa=newderivedNonGen<String>("Valueis:",}}Valueis: 運(yùn)行時(shí)類型識(shí)機(jī)制,也可以采用傳統(tǒng)的方法。比如,instanceof操作符。JVM中,泛型類的對(duì)象總是一個(gè)特定的類型,此時(shí),它不再ainstanceof antnefGc 注意:Integer之類確定的類型。實(shí)際上在測(cè)同樣道理,getClass()返回的也是原始類型。若b是Generic<String>類型,下面a.getClass()== //--------------文件名demoRTTI_1.java,程序10.21----------publicpublicclasspublicstaticvoidmain(Stringargs[]){Generic<Integer>iob=newGeneric<Integer>(100);Generic<String>sob=newGeneric<String>("Good");if(iobinstanceofSystem.out.println("Generic<Integer>objectisinstanceofGeneric");if(iobinstanceofGeneric<?>)System.out.println("Generic<Integer>objectisinstanceofif(iob.getClass()==sob.getClass())System.out.println("Generic<Integer>classequalsGeneric<String>}Generic<Integer>objectisinstanceof Generic<Integer>objectisinstanceofGeneric<?>Generic<Integer>Generic<Integer>objectisinstanceofGeneric<?>Generic<Integer>classequalsGeneric<String>class//--------------文件名demoRTTI_2.java,程序10.22----------publicpublicclasspublicstaticvoidmain(StringsuperGen<Integer>oa=newsuperGen<Integer>(100);derivedGen<Integer,String>ob=newderivedGen<Integer,if(oainstanceofSystem.out.println("superGenobjectisinstanceofderivedGen");if(obinstanceofsuperGen)System.out.println("derivedGenobjectisinstanceofsuperGen");if(oa.getClass()==ob.getClass())System.out.println("superGenclassequalsderivedGen}}derivedGenobjectisinstanceof 強(qiáng)制類型 個(gè)類:superGen和derivedGen。【10.11//--------------文件名demoForceChange.java,程序10.23----------publicpublicclasspublicstaticvoidmain(StringsuperGen<Integer>oa=newsuperGen<Integer>(100);derivedGen<Integer,String>ob=newderivedGen<Integer,String>if((superGen<Integer>)obinstanceofSystem.out.println("derivedGenSystem.out.println("derivedGenobjectischangedtoif((derivedGen<Integer,String>)oainstanceofderivedGen)System.out.println("superGenobjectischangedtoderivedGen");}}derivedGenderivedGenobjectischangedtoExceptioninthread"main"java.lang.ClassCastException:at提示:建議讀者如果不是十分必要,不要做強(qiáng)制類型轉(zhuǎn)換的操作么對(duì)應(yīng)的泛型是否也會(huì)具有相同的繼承關(guān)系呢?比如,Integer是Number的子類,那么Generic<Integer>Generic<Number>的子類呢?答案是:否。比如,下面的代碼將不Generic<Number>Generic<Number>oa=newoaGeneric<Integer>的父類,所以這條語(yǔ)句無(wú)法編譯通過(guò)。事實(shí)上,10.1Generic類之間沒(méi)有繼承 Jvacas文件的細(xì)節(jié)。但在使用泛型時(shí),對(duì)此過(guò)程進(jìn)行一般的了解是必要的,因?yàn)橹挥辛私膺@一細(xì)節(jié),程序員才能理解JavaJDK1.5以前的版本中是沒(méi)有泛型的,為了保證對(duì)以前版本的兼容,Java采用C++的模板完全不同的方式來(lái)處理泛型(盡管它們二者的使用看上去很相似),Java【10.12//--------------文件名Gen.java,程序10.24----------////默認(rèn)情況下,T是由Object限publicclassTob;Gen(Tob){this.ob=getOb(){returnob;}javap CompiledCompiledfrom"Gen.java"publicclassGenjava.lang.Object{java.lang.Objectob; 面將T稱為“占位符”的原因?!?0.13//--------------文件名GenStr.java,程序10.25----------//T//T是由String限publicclassGenStr<TextendsTob;GenStr(Tob){this.ob=getOb(){returnob;}CompiledCompiledfrom"GenStr.java"publicclassGenStrjava.lang.Object{java.lang.Stringob;java.lang.StringgetOb();}Gen<Integer>Gen<Integer>oa=newGen<Integer>(100);Gen<Integer>ob=oa.getOb();Gen<Integer>ob= 具體指定的參數(shù)類型。這一點(diǎn)在10.8.3小節(jié)中已經(jīng)詳細(xì)介紹過(guò)了。也被稱為。主要發(fā)生在下述三種情況。靜態(tài)成員共享問(wèn)//--------------文件名foo.java,程序10
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 口腔科模擬題+參考答案
- 煤礦完工合同范例
- 合同范例內(nèi)容
- 果場(chǎng)合伙合同范例
- 大棚西瓜種植收購(gòu)合同范例
- 校園投票贊助合同范例
- 家庭勞務(wù)雇傭合同范例
- 2025年江蘇貨運(yùn)駕駛從業(yè)資格證考試題庫(kù)
- 合同范例紙質(zhì)
- 《第九課 比比誰(shuí)打字快:詞組輸入》教學(xué)實(shí)錄-2023-2024學(xué)年新世紀(jì)版(2023)三年級(jí)上冊(cè)
- 福建省泉州市2023-2024學(xué)年高一上學(xué)期期末質(zhì)檢英語(yǔ)試題 附答案
- 防止主播跳槽合同模板
- DB13-T 2092-2014 河北省特種設(shè)備使用安全管理規(guī)范
- CMOS-模擬集成電路課件完整
- 2024-2030年中國(guó)養(yǎng)生壺行業(yè)發(fā)展趨勢(shì)及發(fā)展前景研究報(bào)告
- 2024年貴州省六盤水市中考道德與法治試題卷(含答案詳解)
- 浙江省嘉興市2023-2024學(xué)年高一上學(xué)期1月期末考試 英語(yǔ)試題
- 奶茶店租賃合同協(xié)議書(shū)模板
- 2024年快遞員職業(yè)技能大賽考試題庫(kù)(含答案)
- 24秋國(guó)家開(kāi)放大學(xué)《會(huì)計(jì)信息系統(tǒng)(本)》測(cè)試題參考答案
- 2024版視覺(jué)傳達(dá)設(shè)計(jì)專業(yè)本科人才培養(yǎng)方案-定稿
評(píng)論
0/150
提交評(píng)論