一文帶你看懂java 泛型田晚,史上最全面的泛型教學啦辅肾。

認真看這篇文章哈踱,保證你們對泛型又有新的理解,如果沒有的話嚷兔,請順著網(wǎng)線來打我呀还惠。

概述

引用下百度百科的回答

泛型是程序設計語言的一種特性断箫。允許程序員在強類型程序設計語言中編寫代碼時定義一些可變部分馍管,那些部分在使用前必須作出指明钾麸。各種程序設計語言和其編譯器、運行環(huán)境對泛型的支持均不一樣鲫趁。將類型參數(shù)化以達到代碼復用提高軟件開發(fā)工作效率的一種數(shù)據(jù)類型。泛型類是引用類型利虫,是堆對象挨厚,主要是引入了類型參數(shù)這個概念。

我的理解是:泛型就是把類型明確的工作推遲到創(chuàng)建對象或調用方法的時候才去明確的特殊的類型糠惫。

參數(shù)化類型疫剃,把類型當作是參數(shù)一樣傳遞,Object<數(shù)據(jù)類型>這里面只能是引用類型不能是基本類型硼讽。

比如:

Object<Integer>  //true
Object<int> //false

為什么泛型里面數(shù)據(jù)類型不能是基本類型呢巢价?

因為虛擬機在編譯時會把帶泛型的轉換成Object類型,而基本類型不屬于Object類型,所以泛型里面數(shù)據(jù)類型不能是基本類型壤躲。

為什么要使用泛型呢城菊?

Java語言引入泛型的好處是安全簡單。泛型的好處是在編譯的時候檢查類型安全碉克,并且所有的強制轉換都是自動和隱式的凌唬,提高代碼的重用率。

有一點很重要就是消除了強制類型轉換漏麦,減少了出錯機會客税,舉個例子:

public class Test {
    public static void main(String[] args){
        List list = new ArrayList();
        list.add("1"); 
        list.add(1);
        int i = (int)list.get(0); // java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
        int j = (int)list.get(1);
    }
}

上面代碼在編譯期沒有問題,因為list的add方法是Object類型撕贞,所以在編譯期沒有什么問題更耻,但是運行期的時候我們調用 list的時候并不知道list里面具體存了什么類型的參數(shù),所以取的時候有可能就會報類型轉換的錯誤 捏膨。

如果用了泛型上面的錯誤就不會發(fā)生了秧均。

public class Test {
    public static void main(String[] args){
        List<String> list = new ArrayList();
        list.add("1");
        list.add(1);//在編譯期就會出錯,因為用了泛型脊奋,虛擬機就會在編譯期的時候檢查泛型類型安全熬北。
    }
}

泛型只存在于編譯期。

舉個例子诚隙。

public class Test {
    public static void main(String[] args) throws Exception{
        List<String> list = new ArrayList();
        list.add("hello");
        //list.add(23) //編譯期會報錯
        Class c = Class.forName("java.util.ArrayList");
        Method m = c.getMethod("add",Object.class);
        m.invoke(list,23);
        System.out.println(list); // [hello, 23]
    }
}

通過上面可知讶隐,泛型只在編譯期有效,為什么運行期失效了呢久又,這是因為泛型的擦除概念巫延,通俗點來說就是泛型的信息不會進行運行階段。

泛型的使用

泛型有三種實用方式

泛型類:public class Test<T>}{} T表示未知類型

泛型接口: public interface Test<T>{} 和定義類一樣

泛型方法:public <T> void Test(T name){}

泛型類的使用

泛型類在java中有著很重要的地位地消,其中我們用的最多的就是ArrayList,HashMap,HashSet.

既然是帶你看懂Java泛型炉峰,肯定不能源碼里面的那些容器類呀,那些容器類都已經(jīng)很完善了如果要帶你們看的話脉执,肯定會越看越暈的疼阔,所以我們自己定義一個泛型類出來。

//這個T可以換成隨便一個字母 半夷,只不過我寫泛型都用的T婆廊,你可以換成A,B,C...
public class Test<T> {
    T name;
    public Test(T name){
        this.name = name;
    }
    public T getName() {
        return name;
    }

    public void setName(T name) {
        this.name = name;
    }

//如果不傳泛型類型的話巫橄,那么默認的就是Object型什么都可以傳
Test test = new Test("hello");
//傳入的數(shù)據(jù)類型不為基本類型淘邻,否則編譯期會報錯,開頭我解釋過為什么會報錯了
Test<Integer> test1 = new Test<>(418);

泛型接口的使用

泛型接口的定義和泛型類的定義差不多湘换,我們常見的泛型接口就是宾舅,List,Map,Set.

首先老規(guī)矩我們自己定義一個泛型接口统阿。

public interface Test<T>{
    T getName(T name);
}
//如果實現(xiàn)接口的時候不傳入數(shù)據(jù)類型的話,需要將泛型聲明也要寫到類中要不然會報錯
class Test1<T> implements Test<T>{

    @Override
    public T getName(T name) {
        return null;
    }
}

//實現(xiàn)接口的時候傳入數(shù)據(jù)類型的話筹我,就不用把泛型聲明也寫到類中了
class Test2 implements  Test<String>{

    @Override
    public String getName(String name) {
        return name;
    }
}

泛型方法的使用

泛型方法的使用

public <T> void getName(T name){} 
public <T,K> void getNameAndValue(T name, K value){}
public <T,K,V> void getNameAndValueAndV(T name, K value, V v){}//總的來說就是參數(shù)需要多少泛型扶平,返回值前面就得定義幾個泛型要不然編譯期會出錯

泛型通配符

為什么要用通配符呢?

java里面類和類之間是有繼承關系 的崎溃,比如Cat extends Animals,那么Cat就是Animal的子類蜻直,但是集合是沒有繼承這個概念的,比如List<Cat> catListList<Animals> animalList你不能說 animalList是catList的父類袁串,所以很難看出來這兩個類之間的聯(lián)系概而,但是我們現(xiàn)在只想讓list里面只加入Animals的子類怎么辦呢?

  1. 一種是Animals有多少個子類就定義多少個list囱修,這種方法雖然也可以實現(xiàn)但是Animals如果有一百個赎瑰,一千個,一萬個子類呢你這種方法是不是就太耗時了呢破镰。

  2. 第二種就是用通配符來實現(xiàn)餐曼。比如:List<? extends Animals> animals 這個時候animals就只能添加Animals的子類了,一個list搞定鲜漩。

通配符的基本概念源譬?

  1. 無邊界的通配符:? 舉個例子,能接收所有未知類型的泛型

    public class Test {
       public static void main(String []args){
           List<Integer> list = new ArrayList<>();
           list.add(1);
           list.add(2);
           list.add(3);
           list.add(4);
           List<String> stringList = new ArrayList<>();
           stringList.add("h");
           stringList.add("e");
           stringList.add("l");
           stringList.add("l");
           stringList.add("o");
           getList(stringList);
           getList(list);
       }
        //無論傳入什么List都會被接收
       public static List getList(List<?> list){
           return list;
       }
    

    用List<?>聲明的List 不能使用add方法孕似,因為你不知道的類型是什么踩娘,但是list.add(null)就可以,因為null是所有類型都有的喉祭。舉個例子

    public static List getList(List<?> list){
        // list.add(1);//會報參數(shù)不匹配的錯誤,編譯期報錯
        // list.add("hello");//會報參數(shù)不匹配的錯誤,編譯期報錯
           list.add(null);//添加成功
           return list;
    }
    

    用get方法也只能用Object來接收养渴,因為你不知道你的類型是什么。

    public static List getList(List<?> list){
        int i = list.get(0); //編譯期報錯
        String j = list.get(1); //編譯期報錯
        Object o = list.get(3); //運行正確
        return list;
    }
    
  1. 上邊界通配符號:<? extends E> 可以接收E以及E的子類型的泛型泛烙,這里面的E不止是類哦理卑,也可以是接口,看個例子蔽氨。

    //這個是繼承了類的用法
    public class Test {
        public static void main(String[] args) {
            List<Integer> list = new ArrayList<>();
            list.add(1);
            getList(list);
            List<String> strings = new ArrayList<>();
            strings.add("hello");
            getList(strings);//編譯期報錯
        }
    
        public static List getList(List<? extends Number> list) {
            return list;
        }
    }
    
    
    
    public class Test {
        public static void main(String[] args) {
            List<Integer> list = new ArrayList<>();
            list.add(1);
            getList(list);// 編譯期報錯
            List<Test2> test2s = new ArrayList<>();
            getList(test2s);
        }
        //上邊界為接口的實現(xiàn)藐唠,只要是實現(xiàn)了此接口的類都可以被當做泛型傳進來
        public static List getList(List<? extends Test1> list) {
            return list;
        }
    }
    
    interface Test1{
    
    }
    class Test2 implements Test1{}
    

    以上可知上邊界<? extends E>就是你傳入的類型必須得是E的子類,或者是實現(xiàn)接口的類鹉究。

  1. 下邊界通配符號:<? super E> 就是傳入的類型必須得是E以及E的父類中捆,舉個例子

    public class Test {
        public static void main(String[] args) {
            List<Animals> animals = new ArrayList<>();
            getList(animals); 
            List<Cat> cats = new ArrayList<>();
            getList(cats);
            List<Dog> dogs = new ArrayList<>();
            getList(dogs);//編譯出錯,因為Dog不是Cat的父類
    
        }
    
        public static List getList(List<? super Cat> list) {
            return list;
        }
    }
    class Animals{}
    class Cat extends  Animals{}
    class Dog extends  Animals{}
    

The End

我覺得在java里面我們用的最多的泛型就是List,Map這兩個了吧坊饶,其實我們自己編程的時候多用用泛型,可以減少一定的代碼量殴蓬,還能讓代碼看起來更好看 匿级,用雷軍的一句話說蟋滴,別人都說我寫的代碼像詩一樣,希望你們能在java的路上越走遠啊痘绎。

最后津函,喜歡這篇文章的話麻煩的你們的小手點個轉發(fā)點個贊再走吧,你們的每個轉發(fā)點贊都是我寫作的動力孤页。

關注千玨(jue)公眾號尔苦,后臺留言給我一起交流呀。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末行施,一起剝皮案震驚了整個濱河市允坚,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蛾号,老刑警劉巖稠项,帶你破解...
    沈念sama閱讀 216,919評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異鲜结,居然都是意外死亡展运,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,567評論 3 392
  • 文/潘曉璐 我一進店門精刷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來拗胜,“玉大人,你說我怎么就攤上這事怒允」∪恚” “怎么了?”我有些...
    開封第一講書人閱讀 163,316評論 0 353
  • 文/不壞的土叔 我叫張陵误算,是天一觀的道長仰美。 經(jīng)常有香客問我,道長儿礼,這世上最難降的妖魔是什么咖杂? 我笑而不...
    開封第一講書人閱讀 58,294評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮蚊夫,結果婚禮上诉字,老公的妹妹穿的比我還像新娘。我一直安慰自己知纷,他們只是感情好壤圃,可當我...
    茶點故事閱讀 67,318評論 6 390
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著琅轧,像睡著了一般伍绳。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上乍桂,一...
    開封第一講書人閱讀 51,245評論 1 299
  • 那天冲杀,我揣著相機與錄音效床,去河邊找鬼。 笑死权谁,一個胖子當著我的面吹牛剩檀,可吹牛的內容都是我干的。 我是一名探鬼主播旺芽,決...
    沈念sama閱讀 40,120評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼沪猴,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了采章?” 一聲冷哼從身側響起运嗜,我...
    開封第一講書人閱讀 38,964評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎共缕,沒想到半個月后洗出,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,376評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡图谷,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,592評論 2 333
  • 正文 我和宋清朗相戀三年翩活,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片便贵。...
    茶點故事閱讀 39,764評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡菠镇,死狀恐怖,靈堂內的尸體忽然破棺而出承璃,到底是詐尸還是另有隱情利耍,我是刑警寧澤,帶...
    沈念sama閱讀 35,460評論 5 344
  • 正文 年R本政府宣布盔粹,位于F島的核電站隘梨,受9級特大地震影響,放射性物質發(fā)生泄漏舷嗡。R本人自食惡果不足惜轴猎,卻給世界環(huán)境...
    茶點故事閱讀 41,070評論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望进萄。 院中可真熱鬧捻脖,春花似錦、人聲如沸中鼠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,697評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽援雇。三九已至矛渴,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間惫搏,已是汗流浹背具温。 一陣腳步聲響...
    開封第一講書人閱讀 32,846評論 1 269
  • 我被黑心中介騙來泰國打工盗舰, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人桂躏。 一個月前我還...
    沈念sama閱讀 47,819評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像川陆,于是被迫代替她去往敵國和親剂习。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,665評論 2 354

推薦閱讀更多精彩內容