首先說下什麼是定義帶類型參數的泛型例如:java
public static <T, S extends T> void Test<T t,S s> { Systen.out.println(t.getClass().getName()); Systen.out.println(s.getClass().getName()); }
那麼如今就說下我發現的問題,首先咱們不定義這麼複雜的泛型定義一個簡單的:測試
public static <T> void Test<T t> { Systen.out.println(t.getClass().getName()); } public static void main(String[] args){ Test("1");//發現什麼了,打印出來的是java.lang.String Test(1);//java.lang.Integer //嗯,徹底沒有問題 }
好了,下面再看一個code
public static <T> void Test<T t,T a> { Systen.out.println(t.getClass().getName()); Systen.out.println(a.getClass().getName()); } public static void main(String[] args){ Test("1","1"); Test(1,1); Test("1",1); Test(1,"1"); //你們看看編譯能經過嗎? //嗯,試了下能夠,發現徹底沒有問題,只聲明瞭一個泛型T,並且在調用方法的時候,第一個參數已經肯定了泛型的 //類型是String的,那爲何後邊能夠定義Integer類型的那?帶着這個疑惑咱們看下面的一個例子 }
另外一個例子繼承
public static <T,S extends T> void Test(T t ,S b){ } public static void main(String[] args){ Test("1","1"); Test(1,1); Test("1",1); Test(1,"1"); //你們看看編譯能經過嗎? //嗯,報錯了,Test("1",1);Test(1,"1");這兩個有問題,什麼問題那,首先咱們定義了一個泛型T,後來有定義 //了一個泛型S ,可是這個S是繼承T 的,也就是說這個T是什麼類型的,S也就是什麼類型的全部第一個參數聲明爲St//ring的時候,後邊的第二個參數默認也就是String類型了,嗯,咱們大概知道怎麼回事了,可是真是這麼回事嗎,再看另//個例子 }
在一個例子:get
public static void main(String[] args) { a("1","1",1,21); a("1","1",1,"21"); a("1","1","1",21);//看這裏報錯了 } public static <T,S extends T> void a(T t,S s,T a,S d){ System.err.println(t.getClass().getName()); System.err.println(s.getClass().getName()); System.err.println(d.getClass().getName()); } //這是爲何那,只是第三個參數和第四個參數的類型不一樣,位置變換了一下而已,根據個人理解是這樣的,首先編譯器 //查看泛型的類型的時候是從左到右檢查的,咱先看第一個a,首先第一個參數是String,而泛型定義的時候定義了一個 //兩個一組的類型,編譯器會依次檢查有沒有已經聲明的類型,好比第一個參數你傳的是String ,而你a的參數的第一個 //泛型T 就被定義爲String了,以後第二個參數是S,S是繼承自T 的,因此他理所應當的也是String,好了,後邊第三 //個參數又是一個T,這個T是個泛型和前邊的T不是一個,能夠本身在定義一個類型,例如Integer,後邊的問題來 //了,後邊聲明瞭一個S,這個S是什麼類型的那?咱們發現這個S無論是用String類型仍是Integer類型都不會有錯 //這個就有趣了,不過想一想就會發現,咱們定義了兩個泛型T的類型,一個是String,一個是Integer,而S又是集成 //T的,因此S的類型能夠隨便定義爲這兩種中的任意一種了
嘿嘿目前只測試了這幾種,可能還有其餘的問題,暫時還沒看那,若是看了的話會繼續更新的,在這裏作個記錄,以方便之後在看
編譯器