java泛型中占位符T和?有什么區(qū)別
泛型中占位符T和?有什么區(qū)別?這是一個(gè)好問(wèn)題,有的人可能弄不清楚,所以我們這里簡(jiǎn)單的演示一下,相信大家一定能弄清楚的!
先上兩段代碼:
public static <T> void show1(List<T> list){
for (Object object : list) {
System.out.println(object.toString());
}
}
public static void show2(List<?> list) {
for (Object object : list) {
System.out.println(object);
}
}可以看到show1方法中我們使用了T,大家都知道這是泛型的常見(jiàn)寫(xiě)法,那么這里的T指的是某一類(lèi)具體的對(duì)象,list集合里只能存放同一類(lèi)型數(shù)據(jù),如果插入不同類(lèi)型數(shù)據(jù)則會(huì)報(bào)錯(cuò)。
那么show2方法中我們使用的是?,可以看到在void前面并沒(méi)有<T>,?可以表示成占位符,它自己也不知道list集合中會(huì)存放多少種類(lèi)型的數(shù)據(jù),所以這樣就表明我們的list中存放N種數(shù)據(jù)類(lèi)型也是可以的。
我們通過(guò)一段測(cè)試代碼來(lái)直觀的感受一下二者的區(qū)別吧:
public static void test(){
List<Student> list1 = new ArrayList<>();
list1.add(new Student("zhangsan",18,0));
list1.add(new Student("lisi",28,0));
list1.add(new Student("wangwu",24,1));
//這里如果add(new Teacher(...));就會(huì)報(bào)錯(cuò),因?yàn)槲覀円呀?jīng)給List指定了數(shù)據(jù)類(lèi)型為Student
show1(list1);
System.out.println("************分割線**************");
//這里我們并沒(méi)有給List指定具體的數(shù)據(jù)類(lèi)型,可以存放多種類(lèi)型數(shù)據(jù)
List list2 = new ArrayList<>();
list2.add(new Student("zhaoliu",22,1));
list2.add(new Teacher("sunba",30,0));
show2(list2);
}來(lái)看看運(yùn)行結(jié)果:
Student{name='zhangsan', age=18, sex=0}
Student{name='lisi', age=28, sex=0}
Student{name='wangwu', age=24, sex=1}
************分割線**************
Student{name='zhaoliu', age=22, sex=1}
Teacher{name='sunba', age=30, sex=0}
從show2方法可以看出和show1的區(qū)別了,list2存放了Student和Teacher兩種類(lèi)型,同樣可以輸出數(shù)據(jù),所以這就是T和?的區(qū)別啦~小伙伴們了解了吧
下面來(lái)看看?的擴(kuò)展寫(xiě)法:
List<? extends 數(shù)據(jù)類(lèi)型> list
public static void show3(List<? extends Teacher> list) {
for (Object object : list) {
System.out.println(object);
}
}List<? extends Teacher> list這種寫(xiě)法表示可以接收Teacher和它的子類(lèi)數(shù)據(jù)類(lèi)型的list集合,寫(xiě)個(gè)測(cè)試方法show3(list2);試試:
Student{name='zhaoliu', age=22, sex=1}
Teacher{name='sunba', age=30, sex=0}可以看到正常輸出,因?yàn)榧现械臄?shù)據(jù)都是Teacher的子類(lèi)類(lèi)型,如果我們將List<? extends Teacher> list改成List<? extends Student> list會(huì)出現(xiàn)什么情況?

仔細(xì)看這張圖,我們新建了一個(gè)list3并且聲明數(shù)據(jù)類(lèi)型為T(mén)eacher,這個(gè)時(shí)候調(diào)用show3(List<? extends Student> list) 就馬上會(huì)報(bào)錯(cuò)的,錯(cuò)誤信息提示Teacher不能轉(zhuǎn)換成Student,因?yàn)镾tudent是Teacher的子類(lèi),而我們只接受Student及它的子類(lèi),所以當(dāng)然會(huì)報(bào)錯(cuò)了。
List<? super 數(shù)據(jù)類(lèi)型> list
這種寫(xiě)法表示只接收指定的數(shù)據(jù)類(lèi)型及它的父類(lèi)類(lèi)型,也簡(jiǎn)單的寫(xiě)段代碼看看效果:
public static void show4(List<? super Student> list) {
for (Object object : list) {
System.out.println(object);
}
}可以看出來(lái),我們接收的是Student及它父類(lèi)的集合,我們寫(xiě)兩個(gè)集合數(shù)據(jù)然后調(diào)用試試。
List list4 = new ArrayList<>();
list4.add(new Student("sunba",30,0));
list4.add(new Teacher("zhaoliu",22,1));
show4(list4);在list中插入了一個(gè)Student和Teacher對(duì)象,看看結(jié)果:
Student{name='sunba', age=30, sex=0}
Teacher{name='zhaoliu', age=22, sex=1}沒(méi)毛病,正常運(yùn)行并輸出。
下面我們來(lái)看看,如果我們是傳遞的 Student的子類(lèi)的集合會(huì)咋樣

可以看到和之前的一樣,會(huì)報(bào)錯(cuò),理由也是一樣的,以為我們已經(jīng)定義了只能接收Student及其父類(lèi)的數(shù)據(jù)類(lèi)型。
最后來(lái)看一種情況
如果我定義List的時(shí)候沒(méi)有指定數(shù)據(jù)類(lèi)型,并且插入了一個(gè)Child,Student,Teacher,還是調(diào)用show4(List<? super Student> list),會(huì)報(bào)錯(cuò)嗎?不會(huì)報(bào)錯(cuò),運(yùn)行結(jié)果又會(huì)是什么呢?

可以看到這樣并沒(méi)有報(bào)錯(cuò),因?yàn)閘ist可以存放多種數(shù)據(jù)類(lèi)型,那么調(diào)用show4方法時(shí)會(huì)是什么結(jié)果呢?

可以看到程序正常運(yùn)行并輸出結(jié)果,注意一點(diǎn),我們接收的是Student及其父類(lèi)對(duì)象數(shù)據(jù)類(lèi)型,因?yàn)槲覀兊腃hild是繼承Student的,所以程序自動(dòng)將我們的Child轉(zhuǎn)成父類(lèi)Student進(jìn)行輸出,所以大家要注意這一點(diǎn),會(huì)自動(dòng)向上轉(zhuǎn)化。
總結(jié)
相信大家看了這個(gè)以后一定再也不會(huì)弄混二者的區(qū)別了吧,他們倆還是很容易弄清楚的,這些東西只要弄清楚了以后就也忘不掉了
到此這篇關(guān)于java泛型中占位符T和?有什么區(qū)別的文章就介紹到這了,更多相關(guān)java泛型占位符T和?內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JAVA使用hutool工具實(shí)現(xiàn)查詢樹(shù)結(jié)構(gòu)數(shù)據(jù)(省市區(qū))
今天通過(guò)本文給大家分享JAVA使用hutool工具實(shí)現(xiàn)查詢樹(shù)結(jié)構(gòu)數(shù)據(jù)(省市區(qū)),代碼分為表結(jié)構(gòu)和數(shù)據(jù)結(jié)構(gòu),代碼簡(jiǎn)單易懂,對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2021-08-08
Spring中property-placeholder的使用與解析詳解
本篇文章主要介紹了Spring中property-placeholder的使用與解析詳解,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-05-05
SpringBoot+Jersey跨域文件上傳的實(shí)現(xiàn)示例
在SpringBoot開(kāi)發(fā)后端服務(wù)時(shí),我們一般是提供接口給前端使用,本文主要介紹了SpringBoot+Jersey跨域文件上傳的實(shí)現(xiàn)示例,具有一定的參考價(jià)值,感興趣的可以了解一下2024-07-07
使用ThreadPoolExecutor之高效處理并發(fā)任務(wù)
這篇文章主要介紹了使用ThreadPoolExecutor之高效處理并發(fā)任務(wù),具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-07-07
深入理解Java8新特性之Lambda表達(dá)式的基本語(yǔ)法和自定義函數(shù)式接口
Lambda 表達(dá)式,也可稱(chēng)為閉包,它是推動(dòng) Java 8 發(fā)布的最重要新特性。Lambda 允許把函數(shù)作為一個(gè)方法的參數(shù)(函數(shù)作為參數(shù)傳遞進(jìn)方法中)。使用 Lambda 表達(dá)式可以使代碼變的更加簡(jiǎn)潔緊湊2021-11-11
Java中的抽象工廠模式_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
抽象工廠模式是工廠方法模式的升級(jí)版本,他用來(lái)創(chuàng)建一組相關(guān)或者相互依賴(lài)的對(duì)象。下面通過(guò)本文給大家分享Java中的抽象工廠模式,感興趣的朋友一起看看吧2017-08-08
Java AtomicInteger類(lèi)使用方法實(shí)例講解
這篇文章主要介紹了Java AtomicInteger類(lèi)使用方法實(shí)例講解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-06-06

