真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Java中泛型機(jī)制有什么用-創(chuàng)新互聯(lián)

小編給大家分享一下Java中泛型機(jī)制有什么用,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

成都地區(qū)優(yōu)秀IDC服務(wù)器托管提供商(創(chuàng)新互聯(lián)公司).為客戶提供專(zhuān)業(yè)的西部信息中心,四川各地服務(wù)器托管,西部信息中心、多線服務(wù)器托管.托管咨詢專(zhuān)線:18982081108

Java 在 5.0 時(shí)增加了泛型機(jī)制,據(jù)說(shuō)專(zhuān)家們?yōu)榇嘶ㄙM(fèi)了 5 年左右的時(shí)間(聽(tīng)起來(lái)很不容易)。有了泛型之后,尤其是對(duì)集合類(lèi)的使用,就變得更規(guī)范了。

看下面這段簡(jiǎn)單的代碼。

ArrayListlist=newArrayList();list.add("沉默王二");Stringstr=list.get(0);但在沒(méi)有泛型之前該怎么辦呢?

首先,我們需要使用 Object 數(shù)組來(lái)設(shè)計(jì) Arraylist 類(lèi)。

classArraylist{privateObject[]objs;privateinti=0;publicvoidadd(Objectobj){objs[i++]=obj;}publicObjectget(inti){returnobjs[i];}}然后,我們向 Arraylist 中存取數(shù)據(jù)。
Arraylistlist=newArraylist();list.add("沉默王二");list.add(newDate());Stringstr=(String)list.get(0);你有沒(méi)有發(fā)現(xiàn)兩個(gè)問(wèn)題:
  • Arraylist 可以存放任何類(lèi)型的數(shù)據(jù)(既可以存字符串,也可以混入日期),因?yàn)樗蓄?lèi)都繼承自 Object 類(lèi)。

  • 從 Arraylist 取出數(shù)據(jù)的時(shí)候需要強(qiáng)制類(lèi)型轉(zhuǎn)換,因?yàn)榫幾g器并不能確定你取的是字符串還是日期。

對(duì)比一下,你就能明顯地感受到泛型的優(yōu)秀之處:使用類(lèi)型參數(shù)解決了元素的不確定性——參數(shù)類(lèi)型為 String 的集合中是不允許存放其他類(lèi)型元素的,取出數(shù)據(jù)的時(shí)候也不需要強(qiáng)制類(lèi)型轉(zhuǎn)換了。

二哥,怎么設(shè)計(jì)泛型啊?

三妹啊,你一個(gè)小白只要會(huì)用泛型就行了,還想設(shè)計(jì)泛型???!不過(guò),既然你想了解,那么哥義不容辭。

首先,我們來(lái)按照泛型的標(biāo)準(zhǔn)重新設(shè)計(jì)一下 Arraylist 類(lèi)。

classArraylist{privateObject[]elementData;privateintsize=0;publicArraylist(intinitialCapacity){this.elementData=newObject[initialCapacity];}publicbooleanadd(Ee){elementData[size++]=e;returntrue;}EelementData(intindex){return(E)elementData[index];}}

一個(gè)泛型類(lèi)就是具有一個(gè)或多個(gè)類(lèi)型變量的類(lèi)。Arraylist 類(lèi)引入的類(lèi)型變量為 E(Element,元素的首字母),使用尖括號(hào) <> 括起來(lái),放在類(lèi)名的后面。

然后,我們可以用具體的類(lèi)型(比如字符串)替換類(lèi)型變量來(lái)實(shí)例化泛型類(lèi)。

Arraylistlist=newArraylist();list.add("沉默王三");Stringstr=list.get(0);

Date 類(lèi)型也可以的。

Arraylistlist=newArraylist();list.add(newDate());Datedate=list.get(0);

其次,我們還可以在一個(gè)非泛型的類(lèi)(或者泛型類(lèi))中定義泛型方法。

classArraylist{publicT[]toArray(T[]a){return(T[])Arrays.copyOf(elementData,size,a.getClass());}}

不過(guò),說(shuō)實(shí)話,泛型方法的定義看起來(lái)略顯晦澀。來(lái)一副圖吧(注意:方法返回類(lèi)型和方法參數(shù)類(lèi)型至少需要一個(gè))。

Java中泛型機(jī)制有什么用

現(xiàn)在,我們來(lái)調(diào)用一下泛型方法。

Arraylistlist=newArraylist<>(4);list.add("沉");list.add("默");list.add("王");list.add("二");String[]strs=newString[4];strs=list.toArray(strs);for(Stringstr:strs){System.out.println(str);}

最后,我們?cè)賮?lái)說(shuō)說(shuō)泛型變量的限定符 extends。在解釋這個(gè)限定符之前,我們假設(shè)有三個(gè)類(lèi),它們之間的定義是這樣的。

classWanglaoer{publicStringtoString(){return"王老二";}}classWangerextendsWanglaoer{publicStringtoString(){return"王二";}}classWangxiaoerextendsWanger{publicStringtoString(){return"王小二";}}

我們使用限定符 extends 來(lái)重新設(shè)計(jì)一下 Arraylist 類(lèi)。

classArraylist{}

當(dāng)我們向 Arraylist 中添加 Wanglaoer 元素的時(shí)候,編譯器會(huì)提示錯(cuò)誤:Arraylist 只允許添加 Wanger 及其子類(lèi) Wangxiaoer 對(duì)象,不允許添加其父類(lèi) Wanglaoer。

Arraylistlist=newArraylist<>(3);list.add(newWanger());list.add(newWanglaoer());//Themethodadd(Wanger)inthetypeArraylistisnotapplicableforthearguments//(Wanglaoer)list.add(newWangxiaoer());

也就是說(shuō),限定符 extends 可以縮小泛型的類(lèi)型范圍。

二哥,聽(tīng)說(shuō)虛擬機(jī)沒(méi)有泛型?

三妹,你功課做得可以啊,連虛擬機(jī)都知道了啊。哥可以肯定地回答你,虛擬機(jī)是沒(méi)有泛型的。

啰嗦一句哈。我們編寫(xiě)的 Java 代碼(也就是源碼,后綴為 .java 的文件)是不能夠被操作系統(tǒng)直接識(shí)別的,需要先編譯,生成 .class 文件(也就是字節(jié)碼文件)。然后 Java 虛擬機(jī)(JVM)會(huì)充當(dāng)一個(gè)翻譯官的角色,把字節(jié)碼翻譯給操作系統(tǒng)能聽(tīng)得懂的語(yǔ)言,告訴它該干嘛。

怎么確定虛擬機(jī)沒(méi)有泛型呢?我們需要把泛型類(lèi)的字節(jié)碼進(jìn)行反編譯——強(qiáng)烈推薦超神反編譯工具 Jad !

現(xiàn)在,在命令行中敲以下代碼吧(反編譯 Arraylist 的字節(jié)碼文件 Arraylist.class)。

jadArraylist.class

命令執(zhí)行完后,會(huì)生成一個(gè) Arraylist.jad 的文件,用文本編輯工具打開(kāi)后的結(jié)果如下。

//DecompiledbyJadv1.5.8g.Copyright2001PavelKouznetsov.//Jadhomepage:http://www.kpdus.com/jad.html//Decompileroptions:packimports(3)//SourceFileName:Arraylist.javapackagecom.cmower.java_demo.fanxing;importjava.util.Arrays;classArraylist{publicArraylist(intinitialCapacity){size=0;elementData=newObject[initialCapacity];}publicbooleanadd(Objecte){elementData[size++]=e;returntrue;}ObjectelementData(intindex){returnelementData[index];}privateObjectelementData[];privateintsize;}

類(lèi)型變量 消失了,取而代之的是 Object !

既然如此,那如果泛型類(lèi)使用了限定符 extends,結(jié)果會(huì)怎么樣呢?我們先來(lái)看看 Arraylist2 的源碼。

classArraylist2{privateObject[]elementData;privateintsize=0;publicArraylist2(intinitialCapacity){this.elementData=newObject[initialCapacity];}publicbooleanadd(Ee){elementData[size++]=e;returntrue;}EelementData(intindex){return(E)elementData[index];}}字節(jié)碼文件Arraylist2.class使用Jad反編譯后的結(jié)果如下。//DecompiledbyJadv1.5.8g.Copyright2001PavelKouznetsov.//Jadhomepage:http://www.kpdus.com/jad.html//Decompileroptions:packimports(3)//SourceFileName:Arraylist2.javapackagecom.cmower.java_demo.fanxing;//Referencedclassesofpackagecom.cmower.java_demo.fanxing://WangerclassArraylist2{publicArraylist2(intinitialCapacity){size=0;elementData=newObject[initialCapacity];}publicbooleanadd(Wangere){elementData[size++]=e;returntrue;}WangerelementData(intindex){return(Wanger)elementData[index];}privateObjectelementData[];privateintsize;}

類(lèi)型變量 不見(jiàn)了,E 被替換成了 Wanger。

通過(guò)以上兩個(gè)例子說(shuō)明,Java 虛擬機(jī)會(huì)將泛型的類(lèi)型變量擦除,并替換為限定類(lèi)型(沒(méi)有限定的話,就用 Object)。

二哥,類(lèi)型擦除會(huì)有什么問(wèn)題嗎?

三妹啊,你還別說(shuō),類(lèi)型擦除真的會(huì)有一些“問(wèn)題”。

我們來(lái)看一下這段代碼。

publicclassCmower{publicstaticvoidmethod(Arraylistlist){System.out.println("Arraylistlist");}publicstaticvoidmethod(Arraylistlist){System.out.println("Arraylistlist");}}

在淺層的意識(shí)上,我們會(huì)想當(dāng)然地認(rèn)為 Arraylist list 和 Arraylist list 是兩種不同的類(lèi)型,因?yàn)?String 和 Date 是不同的類(lèi)。

但由于類(lèi)型擦除的原因,以上代碼是不會(huì)通過(guò)編譯的——編譯器會(huì)提示一個(gè)錯(cuò)誤(這正是類(lèi)型擦除引發(fā)的那些“問(wèn)題”):

Erasure of method method(Arraylist) is the same as another method in type
Cmower

Erasure of method method(Arraylist) is the same as another method in type
Cmower

大致的意思就是,這兩個(gè)方法的參數(shù)類(lèi)型在擦除后是相同的。

也就是說(shuō),method(Arraylist list) 和 method(Arraylist list) 是同一種參數(shù)類(lèi)型的方法,不能同時(shí)存在。類(lèi)型變量 String 和 Date 在擦除后會(huì)自動(dòng)消失,method 方法的實(shí)際參數(shù)是 Arraylist list。

有句俗話叫做:“百聞不如一見(jiàn)”,但即使見(jiàn)到了也未必為真——泛型的擦除問(wèn)題就可以很好地佐證這個(gè)觀點(diǎn)。

二哥,聽(tīng)說(shuō)泛型還有通配符?

三妹啊,哥突然覺(jué)得你很適合作一枚可愛(ài)的程序媛?。∧氵@預(yù)習(xí)的功課做得可真到家啊,連通配符都知道!

通配符使用英文的問(wèn)號(hào)(?)來(lái)表示。在我們創(chuàng)建一個(gè)泛型對(duì)象時(shí),可以使用關(guān)鍵字 extends 限定子類(lèi),也可以使用關(guān)鍵字 super 限定父類(lèi)。

為了更好地解釋通配符,我們需要對(duì) Arraylist 進(jìn)行一些改進(jìn)。

classArraylist{privateObject[]elementData;privateintsize=0;publicArraylist(intinitialCapacity){this.elementData=newObject[initialCapacity];}publicbooleanadd(Ee){elementData[size++]=e;returntrue;}publicEget(intindex){return(E)elementData[index];}publicintindexOf(Objecto){if(o==null){for(inti=0;i=0;}publicStringtoString(){StringBuildersb=newStringBuilder();for(Objecto:elementData){if(o!=null){Ee=(E)o;sb.append(e.toString());sb.append(',').append('');}}returnsb.toString();}publicintsize(){returnsize;}publicEset(intindex,Eelement){EoldValue=(E)elementData[index];elementData[index]=element;returnoldValue;}}

1)新增 indexOf(Object o) 方法,判斷元素在 Arraylist 中的位置。注意參數(shù)為 Object 而不是泛型 E。

2)新增 contains(Object o) 方法,判斷元素是否在 Arraylist 中。注意參數(shù)為 Object 而不是泛型 E。

3)新增 toString() 方法,方便對(duì) Arraylist 進(jìn)行打印。

4)新增 set(int index, E element) 方法,方便對(duì) Arraylist 元素的更改。

你知道,Arraylist list = new Arraylist(); 這樣的語(yǔ)句是無(wú)法通過(guò)編譯的,盡管 Wangxiaoer 是 Wanger 的子類(lèi)。但如果我們確實(shí)需要這種 “向上轉(zhuǎn)型” 的關(guān)系,該怎么辦呢?這時(shí)候就需要通配符來(lái)發(fā)揮作用了。

利用 形式的通配符,可以實(shí)現(xiàn)泛型的向上轉(zhuǎn)型,來(lái)看例子。

Arraylistlist2=newArraylist<>(4);list2.add(null);//list2.add(newWanger());//list2.add(newWangxiaoer());Wangerw2=list2.get(0);//Wangxiaoerw3=list2.get(1);

list2 的類(lèi)型是 Arraylist,翻譯一下就是,list2 是一個(gè) Arraylist,其類(lèi)型是 Wanger 及其子類(lèi)。

注意,“關(guān)鍵”來(lái)了!list2 并不允許通過(guò) add(E e) 方法向其添加 Wanger 或者 Wangxiaoer 的對(duì)象,唯一例外的是 null。為什么不能存呢?原因還有待探究(苦澀)。

那就奇了怪了,既然不讓存放元素,那要 Arraylist 這樣的 list2 有什么用呢?

雖然不能通過(guò) add(E e) 方法往 list2 中添加元素,但可以給它賦值。

Arraylistlist=newArraylist<>(4);Wangerwanger=newWanger();list.add(wanger);Wangxiaoerwangxiaoer=newWangxiaoer();list.add(wangxiaoer);Arraylistlist2=list;Wangerw2=list2.get(1);System.out.println(w2);System.out.println(list2.indexOf(wanger));System.out.println(list2.contains(newWangxiaoer()));

Arraylist list2 = list; 語(yǔ)句把 list 的值賦予了 list2,此時(shí) list2 == list。由于 list2 不允許往其添加其他元素,所以此時(shí)它是安全的——我們可以從容地對(duì) list2 進(jìn)行 get()、indexOf() 和 contains()。想一想,如果可以向 list2 添加元素的話,這 3 個(gè)方法反而變得不太安全,它們的值可能就會(huì)變。

利用 形式的通配符,可以向 Arraylist 中存入父類(lèi)是 Wanger 的元素,來(lái)看例子。

Arraylistlist3=newArraylist<>(4);list3.add(newWanger());list3.add(newWangxiaoer());//Wangerw3=list3.get(0);

需要注意的是,無(wú)法從 Arraylist 這樣類(lèi)型的 list3 中取出數(shù)據(jù)。為什么不能取呢?原因還有待探究(再次苦澀)。

雖然原因有待探究,但結(jié)論是明確的: 可以取數(shù)據(jù), 可以存數(shù)據(jù)。那么利用這一點(diǎn),我們就可以實(shí)現(xiàn)數(shù)組的拷貝—— 作為源(保證源不會(huì)發(fā)生變化), 作為目標(biāo)(可以保存值)。

publicclassCollections{publicstaticvoidcopy(Arraylistdest,Arraylistsrc){for(inti=0;i

以上是“Java中泛型機(jī)制有什么用”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)-成都網(wǎng)站建設(shè)公司行業(yè)資訊頻道!


網(wǎng)站欄目:Java中泛型機(jī)制有什么用-創(chuàng)新互聯(lián)
URL標(biāo)題:http://weahome.cn/article/giiio.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部