java泛型中占位符T和?有什麼區別

泛型中占位符T和?有什麼區別?這是一個好問題,有的人可能弄不清楚,所以我們這裡簡單的演示一下,相信大傢一定能弄清楚的!

先上兩段代碼:

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,大傢都知道這是泛型的常見寫法,那麼這裡的T指的是某一類具體的對象,list集合裡隻能存放同一類型數據,如果插入不同類型數據則會報錯。

那麼show2方法中我們使用的是?,可以看到在void前面並沒有<T>,?可以表示成占位符,它自己也不知道list集合中會存放多少種類型的數據,所以這樣就表明我們的list中存放N種數據類型也是可以的。

我們通過一段測試代碼來直觀的感受一下二者的區別吧:

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(...));就會報錯,因為我們已經給List指定瞭數據類型為Student
   show1(list1);

   System.out.println("************分割線**************");

   //這裡我們並沒有給List指定具體的數據類型,可以存放多種類型數據
   List list2 = new ArrayList<>();
   list2.add(new Student("zhaoliu",22,1));
   list2.add(new Teacher("sunba",30,0));
   show2(list2);
}

來看看運行結果:

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的區別瞭,list2存放瞭Student和Teacher兩種類型,同樣可以輸出數據,所以這就是T和?的區別啦~小夥伴們瞭解瞭吧

下面來看看?的擴展寫法:

List<? extends 數據類型> list

public static void show3(List<? extends Teacher> list) {
    for (Object object : list) {
        System.out.println(object);
    }
}

List<? extends Teacher> list這種寫法表示可以接收Teacher和它的子類數據類型的list集合,寫個測試方法show3(list2);試試:

Student{name='zhaoliu', age=22, sex=1}
Teacher{name='sunba', age=30, sex=0}

可以看到正常輸出,因為集合中的數據都是Teacher的子類類型,如果我們將List<? extends Teacher> list改成List<? extends Student> list會出現什麼情況?

仔細看這張圖,我們新建瞭一個list3並且聲明數據類型為Teacher,這個時候調用show3(List<? extends Student> list) 就馬上會報錯的,錯誤信息提示Teacher不能轉換成Student,因為Student是Teacher的子類,而我們隻接受Student及它的子類,所以當然會報錯瞭。

List<? super 數據類型> list

這種寫法表示隻接收指定的數據類型及它的父類類型,也簡單的寫段代碼看看效果:

public static void show4(List<? super Student> list) {
    for (Object object : list) {
        System.out.println(object);
    }
}

可以看出來,我們接收的是Student及它父類的集合,我們寫兩個集合數據然後調用試試。

List list4 = new ArrayList<>();
list4.add(new Student("sunba",30,0));
list4.add(new Teacher("zhaoliu",22,1));
show4(list4);

在list中插入瞭一個Student和Teacher對象,看看結果:

Student{name='sunba', age=30, sex=0}
Teacher{name='zhaoliu', age=22, sex=1}

沒毛病,正常運行並輸出。

下面我們來看看,如果我們是傳遞的 Student的子類的集合會咋樣

可以看到和之前的一樣,會報錯,理由也是一樣的,以為我們已經定義瞭隻能接收Student及其父類的數據類型。

最後來看一種情況

如果我定義List的時候沒有指定數據類型,並且插入瞭一個Child,Student,Teacher,還是調用show4(List<? super Student> list),會報錯嗎?不會報錯,運行結果又會是什麼呢?

可以看到這樣並沒有報錯,因為list可以存放多種數據類型,那麼調用show4方法時會是什麼結果呢?

可以看到程序正常運行並輸出結果,註意一點,我們接收的是Student及其父類對象數據類型,因為我們的Child是繼承Student的,所以程序自動將我們的Child轉成父類Student進行輸出,所以大傢要註意這一點,會自動向上轉化。

總結

相信大傢看瞭這個以後一定再也不會弄混二者的區別瞭吧,他們倆還是很容易弄清楚的,這些東西隻要弄清楚瞭以後就也忘不掉瞭

到此這篇關於java泛型中占位符T和?有什麼區別的文章就介紹到這瞭,更多相關java泛型占位符T和?內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: