本篇內(nèi)容介紹了“怎么使用Java泛型”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!
創(chuàng)新互聯(lián)是一家集網(wǎng)站建設(shè),富裕企業(yè)網(wǎng)站建設(shè),富裕品牌網(wǎng)站建設(shè),網(wǎng)站定制,富裕網(wǎng)站建設(shè)報(bào)價(jià),網(wǎng)絡(luò)營(yíng)銷,網(wǎng)絡(luò)優(yōu)化,富裕網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強(qiáng)企業(yè)競(jìng)爭(zhēng)力??沙浞譂M足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時(shí)我們時(shí)刻保持專業(yè)、時(shí)尚、前沿,時(shí)刻以成就客戶成長(zhǎng)自我,堅(jiān)持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實(shí)用型網(wǎng)站。
一般定義如下,即方法的前面加了個(gè)
public class FTest { publicList f(T t){...}; }
三種泛型參數(shù)推斷方式:
1、直接在f()前面加確定泛型
fTest.f(xxx)
2、通過(guò)輸入?yún)?shù)確定, 下面這個(gè)推斷為Integer
int number = 0; fTest.f(number)
3、可通過(guò) 返回值 確定
Listlist = fTest.f(xxx);
Q: 下面這段代碼哪里有問(wèn)題? 是toString()那里嗎?
public class A{ public static void test(T t){ System.out.println(t.toString()); } }
A:test是static方法, 因此無(wú)法感知A
需要改成
public static
toString()那里沒(méi)問(wèn)題,toString就是Object的方法。
Q: 泛型參數(shù)T在運(yùn)行時(shí),會(huì)變成什么?
A: 統(tǒng)一變成Object且不包含任何類型信息。
Q: 泛型參數(shù)T可以可以使用instanceof做比較嗎?
class A{ void f(Object arg) if(arg instanceof T) { ... } }
A: 不能,編譯器會(huì)報(bào)錯(cuò)。
Q: 泛型參數(shù)T可以進(jìn)行new T()或者new T[]操作嗎?
A: 不能,編譯器會(huì)報(bào)錯(cuò)。
Q: 能調(diào)用泛型參數(shù)對(duì)象里的方法嗎?
T.f();
A: 只能調(diào)用Object的方法。
Q: 可以用T做強(qiáng)制轉(zhuǎn)化嗎?
T t = (T)object;
A: 能運(yùn)行, 但不會(huì)真正發(fā)生轉(zhuǎn)型, 編譯時(shí)會(huì)觸發(fā)waring警告。
先假定有2個(gè)類, 基類Parent 和子類Child
class Parent{} class Child extends Parent{}
回答以下問(wèn)題:
Q:下面這句話有問(wèn)題嗎?
Listlist = new ArrayList ()
A:有問(wèn)題,編譯就錯(cuò)誤了。 List
Q:
List extends Parent> list = new ArrayList();
這個(gè)list有什么特點(diǎn)?
A:這個(gè)list可以調(diào)用A a = list.get(), 但是不能list.add(new Parent())
原因:
list.get()所做的操作是在返回時(shí), 把內(nèi)部的 extend Parent> 強(qiáng)轉(zhuǎn)成Parent, 是合理的,任何Parent的子類都可以轉(zhuǎn)成Parent
list.add(new Parent())所做的操作是在輸入時(shí), 把外部的A轉(zhuǎn)成內(nèi)部的 extend Parent>, 這是不合理的,因?yàn)槲覀儾恢肋@個(gè)Parent對(duì)象可以轉(zhuǎn)成哪個(gè)Parent的子類。
Q:
List super Child> list = new ArrayList();
這個(gè)list有什么特點(diǎn)?
下面誰(shuí)會(huì)報(bào)錯(cuò)
list.add(new Child()) list.add(new Parent()) Parent a= list.get(); Child b = list.get()
A:截圖如下:
Child c = list.get() 或者Parent p = list.get()所做的操作是在返回時(shí), 把內(nèi)部的 super Child> 強(qiáng)轉(zhuǎn)成外部的Parent或者child, 是不合理的, 因?yàn)榫幾g器覺(jué)得child的父類 不一定 能轉(zhuǎn)成parent或者child,所以禁止了這種行為( 比如parent的父類是object, 但object不一定就能轉(zhuǎn)成parent或者child)。*list.add(new Child())所做的操作是在輸入時(shí), 把外部的child或者parent轉(zhuǎn)成內(nèi)部的 super Child>, 這是合理的,因?yàn)閏hild和parent一定能轉(zhuǎn)成child的父類。
Q:
List> list = new ArrayList();
這個(gè)list有什么特點(diǎn)?
A:get和add都不行,只能做remove等無(wú)返回值無(wú)輸入A的操作。
PS: 注意,不是說(shuō)不能調(diào)用get或add方法, 而是調(diào)用get或add時(shí),不能使用A這個(gè)對(duì)象去操作。
即無(wú)法做add(A) 或者 A a = get(0)
但是可以做add(object) 或者Object o = get(0)
因?yàn)椋靠梢赞D(zhuǎn)為Object, 但是無(wú)法轉(zhuǎn)為A。
Q:下面這個(gè)代碼會(huì)報(bào)錯(cuò)嗎?
ListfruitList = new ArrayList<>(); fruitList.add(new Fruit()); List appleList = new ArrayList<>(); appleList.add(new Apple()); fruitList.addAll(appleList); System.out.println(fruitList);
A:不會(huì)報(bào)錯(cuò)。會(huì)正常打印結(jié)果。
PECS原則
注意PECS原則和上面的區(qū)別!
上面之前提到的? extend或者? supert, 都是在聲明對(duì)象的時(shí)候用的。
而PECS原則是用于泛型對(duì)象的方法輸入?yún)?shù)!
假設(shè)有一個(gè)類定義如下:
public static class MyList{ List list = new ArrayList<>(); // 把輸入?yún)?shù)塞給自己,類似于生產(chǎn)操作 public void pushList(List t) { list.addAll(t); } // 把自己的內(nèi)容塞給輸入?yún)?shù),類似于讓輸入?yún)?shù)做消費(fèi)。 public void pollList(List t) { t.addAll(list); } }
則T就是泛型參數(shù)。
Q:下面代碼能正常運(yùn)行嗎?
MyListmyList = new MyList<>(); List intList = new ArrayList<>(); myList.pushList(intList); List
A:不能正常運(yùn)行, pushList和pollList都會(huì)報(bào)錯(cuò)
因?yàn)榫幾g器檢查后,認(rèn)為 List
Q: 如果上文要支持pushList,應(yīng)該怎么修改pushList方法的定義?
A:改成這樣:
// 把輸入?yún)?shù)塞給自己,類似于生產(chǎn)操作 public void pushList(List extends T> t) { list.addAll(t); }
即編譯器認(rèn)為,List
Q: 如果要支持pollList,怎么修改定義?
A:
// 把自己的內(nèi)容塞給輸入?yún)?shù),類似于讓輸入?yún)?shù)做消費(fèi)。 public void pollList(List super T> t) { t.addAll(list); }
因?yàn)槭前炎约旱臇|西塞給輸入?yún)?shù), 而想要能塞進(jìn)去,必須保證自己這個(gè)T,是輸入?yún)?shù)的子類,反過(guò)來(lái)說(shuō),輸入?yún)?shù)必須是T的父類,所以用super
于是編譯器認(rèn)為,List
PECS原則出自Effective Java, 注意只是一個(gè)編程建議而已!
如果有一個(gè)類A,泛型參數(shù)為T
如果他一般只用于接收輸入容器List后,塞入自己內(nèi)部的T容器, 則類A就叫生產(chǎn)者, 因此輸入?yún)?shù)最好定義為 extend T>最好, 以便能接收任何T子類的容器。
如果他一般只用于接收輸入容器后List, 把自己內(nèi)部的T元素塞給它, 那么這個(gè)類A就叫消費(fèi)者, 輸入?yún)?shù)最好定義為 super T>\ 最好, 以便自己的T元素能塞給任何T元素的父類容器。
“怎么使用Java泛型”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!