怒幹一萬字,帶你真正理解Java的泛型!

什麼是泛型(先理解是個啥)

在學習Java基礎的過程中,泛型絕對算得上是一個比較難理解的知識點,尤其對於初學者而言,而且就算是已經有基礎的Java程序員,可能對泛型的理解也不是那麼透徹,屬於那種看了明白,時間長了就忘的那種,究其根本,還是對泛型不夠理解。


大部分人對泛型的認識:“基礎知識,但是比較模糊”

爲啥要有泛型

泛型這個概念是在Java1.5提出來的,之前是沒有的,那爲什麼之前沒有,現在要提出來這個概念呢?那你就得想啊:


1、要麼是之前的技術太垃圾了,得升級換代下
2、要麼是技術發展,搞出來的新玩意,讓Java更好用
3、要麼就是填坑,之前的有部分,搞個出來填坑
4、……


那你看,這個泛型,有可能是啥,實際上它就是填坑的,說這個之前,咱們先來看一段代碼:


image.png


這段代碼沒有看不懂的吧,就是簡單的一個List集合,這裏可能需要你額外注意的就是我這裏定義的List不是這樣的哦:

List<String> stringList = new ArrayList<String>();


不知道你看出來區別了嗎?這個應該是大部分我們用的時候會定義的那種,熟悉泛型的可能知道這是怎麼回事,但是不熟悉泛型的就記住這麼用就ok了。


繼續看上面我舉的那個例子,這裏我想說明的就是這裏定義的List集合是什麼都能裝的,集合一般啥用,不就是往裏面存放數據的嘛,把集合看做一個房子,裏面可以進去老人和小孩,當然各種貓啊狗啊都可以進去,來,上圖:


image.png


咋樣,我的繪畫功底還是可以吧,List就好比一個房子,裏面是可以進人,當然也可以進動物,比如各種各樣的小貓小狗啊,當然了,List這裏可進入的就是數據了,比如字符串啊,整型啊等等。


這個時候就會產生一個問題,啥問題嘞,你看啊,這座房子裏面可以進入各種各樣的物種,就是各種類型的啊,如果這個房子會說話的話,它就說了“啥玩意啊,你們啥都往我這來,啥品種都行,也太亂了吧,都記不清楚你們誰是誰了,算了我也不記住你們誰是啥類型了,進來的統一當做‘活物’吧”


就是說啊,對於房子來說,不管你進來的是個啥,我統一把你們當做“活物”,在我這裏你們就是一個類型的,同樣的,放到List集合這裏來說的話,也是這樣的,就是你字符串啊,整型啊都可以放入List集合中,那麼List也說了,我不記住你們到底哪個是字符串哪個是整型,在我這裏統一把你們看做是Object類,至於爲啥是Object類,這是因爲Object是一切類的父類啊,所以沒有比它更合適啦,不管你是字符串還是整型,你們一定都是Object類型的,這點容易理解吧。


這樣看似挺完美的,但是也有潛在的問題啊,什麼問題嘞,你看啊,我們還拿房子來說,對於房子來說,在房子裏面的都被看成是“活物”類型了,那麼如果我要從房子裏找一個小狗出來,那麼我找出來的類型都是“活物”,可是我要的是小狗啊,你給我來個“活物”,不符合我的要求啊,怎麼辦?大家都知道有個強制類型轉換吧,好吧,我就把“活物”給你強制轉換成小狗,這不就符合要求了,但是這樣問題就來了,假如你找出來的就是個小狗,你把它強制轉換成小狗,那倒也沒啥,但是你也有可能會找出來個人啊,這時候你要把一個人強制轉換成小狗,擱誰誰也不樂意啊,你說是不是。


同樣的,對於List集合也是這樣,你什麼都可以往裏面存儲,然後統一被看成是Object類型,這個時候如果我們從List集合中取值的話,那就要用到強制轉換了,需要把Object類型轉換成我們要的類型,比如我們想要字符串,如果取出的本來就是字符串,那轉成字符串沒啥關係,但是如果取出來的是整型嘞,強制轉換成字符串,那整型還不樂意嘞,於是乎,程序就要給你報錯了,來來,看看代碼:


image.png


咋一看,貌似沒啥問題,編譯也沒報錯啥的,我們運行一下看看:


image.png


吆喝,運行報錯了,這個錯也簡單,就是不能將整型Integer轉換成String字符串類型,就是類型不匹配啊,這裏要記住這個錯誤類型叫做:ClassCastException

看到這裏你也許就明白了,我定義一個List集合,本來只想往裏面存入字符串嘞,但是不知怎麼滴,裏面混入了一個整型,因爲List並不知道進來的都是什麼類型,反正都看作Object類型,都可以進來,那麼我們取數據的時候就會發生ClassCastException錯誤。

那這不行啊,我給你List裏面存一個數據,我是希望你記住我傳入的是什麼類型的數據的,其他的就不允許再傳入了,這樣我取值的時候也不用強制類型轉換,也就不會發生ClassCastException了。


這個你能想到,那麼JDK官方更加能想到,於是乎,在Java1.5版本中就引入了泛型的概念,而引入泛型的很大一部分原因就是爲了解決我們上述的問題,說白了就是我希望集合可以記得住我存進去的數據是什麼類型的,以此做一個篩選,不是同類型的就不允許在一塊存放,這樣也避免了ClassCastException錯誤的出現,因爲都是同一類型,也就沒必要做強制類型轉換了。


所以,你現在知道了爲啥要有泛型了吧,當然,泛型的引入大部分原因是爲了彌補集合的一個缺點,但是泛型的應用是很廣的,不僅僅侷限於Java的集合。

泛型的定義和理解


以上還算詳細的和大家介紹了爲啥要有泛型的出現,那麼泛型是如何定義的呢?

泛型就是參數化類型,也就是說把我們要操作的類型作爲了一個參數,比如我們創建集合的時候,允許我們可以指定集合中元素的數據類型。

在JDK1.5中引入了“參數化類型”的概念,這個就是泛型,也就是說泛型和參數化類型是等價的,一回事,那麼我們來理解理解啥是參數化類型。

參數化類型


我們看看字面意思,參數化參數化,你想啊,我們有時候看一些魔幻電視劇,比如說某個人獸化了,大致知道啥意思吧,就是他變成了一個怪獸,變形了,哈哈,那麼這裏的參數化意思大概是不是就是變成了一個參數的意思呢?那麼後面還有一個類型,組合起來是不是就是“把類型變成了參數”,那類型是啥啊,不就是String類型,Integer類型這些嘛,現在把這些類型都作爲了參數,這就是參數化類型了。


不知道我表達的是否清楚,你明白嗎?


好了,來看看泛型到底長啥樣吧:

List<String> stringList = new ArrayList<String>();

就是這個,我們經常這樣操作的,它就是泛型的應用,你看看它和如下沒有使用泛型的有啥區別:

List stringList = new ArrayList();

很容易看出,就是多了一個這個,那麼該如何進一步去理解它嘞?

理解泛型


還記得之前我們說的吧,泛型的引入很大一部分原因是爲了讓集合能夠記住他裏面的元素的數據類型,怎麼讓它記住嘞,實際上實現也很簡單,就是隻傳入特定的類型,比如要傳入字符串類型,那麼久只能傳入字符串類型,像整型類型及其他類型就是不允許進入的,這樣的話就能保證集合中的元素都是統一的類型,集合自然就能記住了。


我們再來看之前舉的那個房子的例子:


image.png


通俗易懂吧,之前這個房子是開放的,誰都能進,現在嘞,我這個房子是用作狗屋的,自然是隻提供小狗來住,那麼其他的就不允許進入,你一個人讓你進你也不進啊,怎麼搞嘞,那就是在門口搞個檢查裝置,就好比安檢,首先告訴安檢,只能讓小狗進,其他的不讓進,於是乎,每過來一個,安檢都要檢查下是不是指定的小狗類型,不是的話不讓進,是的話就進去,如此一來這個屋子裏就都是小狗了,名副其實的狗屋啊。


那放到集合也是一樣的,現在要理解的就是如何給這集合加上安檢啊,再來看沒使用泛型的時候:

List stringList = new ArrayList();

這個時候是開放的,各個數據類型的都可以存放到這個List集合中,現在看下使用了泛型的:

List<String> stringList = new ArrayList<String>();

大家也看到了,就是多了個,我們在實際代碼中看下:


image.png


顯而易見啊,報錯了,說是我需要一個String,你給傳入一個int,不符合要求,那就不能存入,所以啊,你看明白了嗎?List是一個集合,可以往裏面存入數據,現在要進行限制,不是什麼類型的都能存入,那就對存入的數據進行檢查,怎麼搞,那就在List後面加個,就成了List,看到沒,這個是不是就和我們上面舉例子中的那個安檢很像,負責檢查進來的數據,首先給它指定一個數據類型,這裏就是String,然後就是檢查,不是String的都不讓存進來,所以啊,這個就是一個安檢的作用啊,其中的String就是指定的數據類型,這就是泛型啊,也就是參數化類型,String是字符串類型,這裏就作爲一個參數放在這裏,保存進List集合中的元素都要是String類型的。


咋樣,明白沒?這就是泛型啊,把String作爲一個參數,類型參數化了,你看,是不是這麼回事。


這樣一看,是不是覺得泛型也挺好理解的,其實這只是對泛型的基本理解,泛型還是有不少內容的,在理解了泛型的基本概念之後,我們還需要看看泛型的其他內容,當然,我必須告訴你,即使上面我講的你明白了,接下來的內容同樣有可能讓你費解,一起來看下!

泛型進階

菱形語法


咋一看,這個很高級啊,啥意思嘞,其實看代碼就知道怎麼回事,我們上面舉了這樣的集合泛型代碼:

List<String> stringList = new ArrayList<String>();


你平常是這樣寫的嗎?我猜有這樣寫的:

List<String> stringList = new ArrayList<>();


有啥區別,很簡單,就是後面的ArrayList後面有尖括號內有沒有這個String,也就是類型參數,這個理解吧,按照我們上面說的,這裏加上是爲了指明集合中元素的數據類型,那麼後面的不寫也行嗎?在Java7之前是必須寫的,也就是必須是這樣的形式:


List<String> stringList = new ArrayList<String>();

但是在Java7開始就可以這樣寫了:

List<String> stringList = new ArrayList<>();


因爲在Java7中是可以通過前面的類型參數去推導出ArrayList中的數據類型的,也就是類型參數不需要了,但是這個<>尖括號是必須的,至於尖括號中的類型,是可以自動被推導出來的,這個就叫做菱形語法,爲啥叫菱形語法嘞,因爲這個<>尖括號像菱形啊……

理解類型參數(重點)


還記得什麼是類型參數嗎?看這行代碼:

List<String> stringList = new ArrayList<>();


泛型的本質是參數化類型,就是把類型當做參數了,而這個類型參數就是尖括號內的東西了,在上面的這行代碼中,所謂的類型參數就是這個String了,這點明白吧,另外啊,我們都是到Java中的方法中有形參和實參,這個都知道怎麼回事吧,那麼這裏類型參數其實也是有區別的,它也是分爲類型形參和類型實參。


那啥是類型形參,啥又是類型實參啊?是不是覺得理解不了?彆着急,經過我下面的解釋,你就會覺得這是如此的簡單。


我們上面寫的這行代碼:

List<String> stringList = new ArrayList<>();

這裏的類型參數String其實就是類型實參了,也就是實際的類型參數,這樣的類型參數其實就是各個數據類型,泛型不就是參數化類型嘛,類型都被當做參數使用,所以這裏的String其實就是實際的類型實參,是個字符串類型,咋樣,理解吧?


那啥是類型形參呢?我們來看看List接口是如何定義的?


image.png


源碼中List接口是這樣定義的,當然,看到尖括號,這就是泛型,只不過好像跟我們之前看的不太一一樣,之前這裏的尖括號都是具體的類型,比如String,這裏弄了一個E,這是啥玩意啊。


首先啊,你看,還記得Lsit集合人家是什麼都可以存儲的嘛,也就是整型啊,字符串都可以,現在使用泛型之後,相當於你可以這樣寫代碼:

List<String> stringList = new ArrayList<>();

那麼你這裏的List集合就只能存儲字符串類型的,當然,如果我想讓List集合專門存儲整型數據呢?那是不是要這樣寫:

List<Integer> list = new ArrayList<>();

可是這樣的話,你發現問題沒?那我源碼中的List該怎樣?現在要求就是我實際寫代碼中List後面的泛型可以寫成各種數據類型,這就要求源碼中的List定義必須是具備通用特性的,那就用個啥來做個抽象的,泛型中就是使用一些大寫的英文字母來作爲類型形參,比如這裏的E就是一個類型形參,實際中你可以寫成String啊或者Interger,以便達到List集合只存儲特定類型數據的目的,而String這些就是類型實參了。


咋樣,明白吧,我之前學習這裏的時候也比較疑惑這個E是啥啊,想必大家也見過T,這都是啥,這些其實就是泛型中的類型形參,我們在創建具體的類,接口或者方法的時候可以把這些類型形參轉換成具體的類型形參,大家可以看看Map的定義,是這樣的:


image.png


這裏是一個K和一個V,所以啊這些都是有個基本命名的,大致有如下這些:

E 元素 集合框架使用
K 鍵 映射關係鍵的類型
V 值 映射關係中值得類型
N 數字 主要用於表示數字
T 通用類型1
S 通用類型1
U 通用類型1
V通用類型1


咋樣,看到這裏是不是有種豁然開朗的感覺呢?這些就是實際的類型形參,比如上面的Map,類型形參是這樣的:

Map<K,V>

實際的類型實參樣式是這樣的:

Map<String,String>

ok了吧!理解力類型參數的形參和實參,我們再看接下來的內容。

泛型使用


我們在上面介紹泛型的時候,基本上都是使用集合類來說明,這很大一部分原因是因爲泛型的提出有相當大的原因是爲了彌補集合的缺陷,當然我也說了,泛型絕不僅僅是侷限於集合,我們可以自定義泛型,比如自定義泛型接口和泛型類以及方法。

1、定義泛型接口


我們還是再來看下JDK中的List的定義,就是它:


image.png


這是定義了一個泛型的List接口,接下來我們來自己定義一個泛型接口,看看是怎麼定義的,來,上代碼:


image.png


我們這裏自定義了一個泛型接口,這個泛型的類型形參是E,包含一個showTypeName方法,目的是打印出泛型實際類型實參的類型名稱,接下來寫一個類去實現這個泛型接口:


image.png


這裏要注意了,我們寫一個類,然後去實現上面我們自定義的泛型接口,這時候我們的類名後面也是要寫上泛型的,就是不能這樣,否則報錯:


image.png


然後就是實現泛型接口中的方法了,獲取傳入的類型實參的類型名稱,接下來我們使用這個類看下:


image.png


到這裏是不是就比較熟悉啦,跟我們之前一直舉例的List集合有點相似吧,我們看輸出結果:


image.png


得出我們輸入的類型形參類型是String類型,以上就是泛型接口定義的一個非常簡單的例子了,咋樣,不知道你看明白了嗎?

2、自定義泛型類


上面我們簡單說了下泛型接口的自定義,大致上就是你要知道泛型接口如何定義,類如何去實現一個泛型接口,接下來我門來看如何自定義一個泛型類,直接看代碼:


image.png


這裏簡單自定義了一個泛型類,這裏要注意,我門上面說過了什麼是類型形參,並且介紹了幾個約定俗成的,實際上這裏的類型形參,你用任何一個大寫的英文字母都是ok的,比如這裏我就用了一個大寫的G,然後看看如何使用這個泛型類:


image.png


我們再來看看輸出結果:


image.png


咋樣,泛型類的自定義是不是也比較簡單,接下來我們看看,一個類如何去繼承一個泛型類。

3、繼承泛型類


直接看代碼吧:


image.png


這裏就是直接繼承了上述我們實現的泛型類,這裏要注意了,我們繼承的泛型類,不能再是類型形參的形式了,也就是不能這個樣子:


image.png


也就是當你繼承了一個泛型類的時候,就要指定真實的類型實參,這個時候就要確定類型了。

4、原始類型


我們上面說了繼承泛型類的時候,後面不能再跟泛型形參的形式了,但是你是可以完全去除泛型的,也就是這樣的形式:


image.png


這樣也可以的,這被稱作是原始類型,那麼這樣的話,實際使用輸出是什麼呢?我們來使用這個類:


image.png


這時候其實就是把原先的類型形參G當做Object類型的了,而之前我們這樣的形式:


image.png


就相當於把原先的類型形參G全部當做是String類型了,所以你這裏就會報錯了:


image.png


因爲這時候就只能傳入String了。

並不存在泛型類


我們拿JDK中的List來舉例說明,首先看下面的代碼:

List<String> stringList = new ArrayList<>();

這行代碼想必你已經非常熟悉了吧,再看個熟悉的代碼:

List stringList = new ArrayList();

經過上面那麼多的講解,你肯定知道了,上面那種我們使用了泛型的形式,下面則沒有,也就是說本身List是什麼都可以存儲的,但是現在加上泛型之後,就只能存儲特定數據類型了,比如這裏的List,也就是從List變成了List了,但是實際上啊,這裏並沒有生成新的List,其實本質上還是List,只不過List做了規定,只能裝載String類型的數據,但是實際上List還是原來的那個List,所以啊,實現類ArrayList並不是一個新的類,不過可以看做是ArrayList的一個子類。


所以啊,泛型類,實際上是不存在的。

通配符


泛型中還有個通配符的概念,這個該怎麼理解呢?還是看例子比較好理解,來看代碼:


image.png


假如這裏有這麼一個方法,也沒啥特別,要非說特別那就是方法中的參數是一個List,爲啥特別,因爲List是一個泛型接口啊,你看:


image.png


但是上面我們的List並沒有指定實際的類型實參,這樣就會產生一些問題,它會產生泛型警告的問題,那麼最好我們還是指定實際的類型形參,但是這裏也有問題啊,就是這裏我並不確定以後傳入過來的List的實際類型實參是啥,也就是說可能傳入這樣的一個List:

List<String> stringList = new ArrayList<>();

也有可能傳入這樣的一個List:

List<String> integerList = new ArrayList<>();

那該怎麼指定嘞?這樣嗎:


image.png


看着好像很對,我們試試:


image.png


很不幸,這裏報錯了,其實這裏一句話可以概括:

String是Object的子類,但是List卻不是List的子類


記住這個,就知道這裏肯定是不行的,那該怎麼辦嘞?這裏就要使用到通配符了,就是這樣:


image.png


就一個問號就搞定啦,這個時候我們使用這個Test方法的時候就是既可以傳入這樣的List:

List<String> stringList = new ArrayList<>();

也可以傳入這樣的List:

所以啊,使用通配符之後可以傳入的類型就多了,但是有的時候可能不需要傳入所有的,希望還是有一定的限制的,這個時候就需要通配符的上下限設置了,關於這個,限於篇幅問題,就不展開來講了。

泛型方法

這裏把泛型方法單獨拿出來講是覺得這個泛型方法理解起來還是需要費點勁兒的!實際情況也確實如此,泛型方法有點不好理解。


那啥是泛型方法嘞,簡單來說啊,泛型方法就是:

聲明方法的時候,可以定義一個或多個泛型形參


這裏我們拿泛型類來對比一下,對於泛型類,比如這個:


image.png


我們在實例化這個類的時候需要指明具體的類型實參,比如是String還是Intenger之類的,那麼對於泛型方法而言,它就是在定義的時候是泛型形參,而實際調用的時候需要指定泛型實參(也就是泛型的具體類型)

定義及使用泛型方法


接下來我們來看如何定義泛型,首先我們來看一個正常的方法定義:


image.png


這是一個很正常的方法定義,但是裏面的邏輯似乎不正常,爲啥?覺得這樣沒必要啊,你看我們這裏需要給參數傳入的就是String類型,你這裏還輸出類型名稱,好像只有給你輸出來你才相信似的,好像是這兒回事,那我們接着來看,如何定義一個泛型方法。


你想啊,我們怎麼定義類,是不是有個關鍵字class,如何定義接口呢?是不是用關鍵字interface,所以,定義這些比較特殊的東西,必定有個特殊的東西,那麼如何定義泛型方法呢?你看:


image.png


這裏就簡單定義了一個泛型方法,這裏需要注意的就是,你憑啥說你定義的是一個泛型方法呢?這裏的一個象徵就是紅框中的泛型,也就是說啊,你要定義一個泛型方法的話,那麼你就必須在權限修飾符(這裏是public)和返回值之間寫上,這個是泛型標誌,代表你這個是一個泛型方法,對了,這裏的T就是個泛型形參,也可以是其他的大寫字母,這個之前講過的,所以啊,你在看這個泛型方法,比如我們調用這個泛型方法:


image.png


是不是覺得邏輯沒啥問題啊,因爲傳入的是個泛型,所以這裏通過一個泛型方法,可以傳入不同的類型,以便查看其類型,這裏要注意了,我們寫的平常的方法,方法傳入的是確定的類型,但是使用泛型後,可以傳入各種類型,那麼就可以測試一些不知道是什麼類型的類型名稱了,可能有點繞,理解下!


所以啊,泛型方法的定義的語法如下:

修飾符 <T,E,……> 返回值類型 方法名稱(形參列表){
方法體……
}


我們來對照一下我們定義的泛型方法:


image.png


這裏的public就是修飾符,就是泛型列表,爲啥說列表,其實是它可以包含多個泛型形參名稱,也就是那些個大寫的英文字母,後面的void就是返回值類型了,然後就是方法名稱和形參列表了。

重點總結


我們還是來看這個泛型方法的定義:


image.png


這裏有幾個知識點需要強調一下:


1、權限修飾符和返回值中間的這個泛型列表,也即是很重要,就相當於是泛型方法的標誌,有了這個你才能叫做泛型方法
2、代表將使用泛型類型T,只有這個時候,你在方法中才可以使用泛型類型T
3、另外你需要知道的就是這個T啊就是泛型形參的命名,可以是T,E,K等等這些,反正就是大寫的英文字母就ok了

泛型方法的的學習建議


對於Java基礎中的泛型這塊,我一直覺得是個比較重要的知識點,當然,事實也是如此,所以這個知識點需要理解透徹了,但是另外一個現實情況就是,泛型的理解還是有一定門檻的,尤其對於初學者而言,那麼泛型中的泛型方法可能又稍微難理解一點,那麼對於這塊的學習,剛開始不建議死扣,有個基本認識即可,比如我上面介紹的那些關於泛型方法的基本知識點,剛開始瞭解這些即可,當然,泛型方法不僅僅是這些,只不過我們暫且不深入學習。


學習還是要一步步來,後續會單獨出文章詳細聊聊泛型方法的。

泛型擦除與轉換


這個泛型擦除是啥嘞?一般的話面試的時候要是問泛型的話,那就大概率會被問到這個泛型擦除了,先來看一段代碼:


image.png


猜想一下,這兩個ArrayList的類型一樣嗎?看一下結果:


image.png


可以看到,這兩個是完全一樣的,也就是說,這裏的泛型實參String和Integer並沒有對ArrayList造成什麼本質上的影響,其實這裏蠻好理解的:

這裏的泛型就相當於一個安檢,指定了一個具體的數據類型,想要往這個集合中存入數據就得經過泛型這個安檢檢查,和指定數據類型不一樣的都不允許存儲,這就保證了存儲的類型都是指定的類型,也就是說啊,我這個集合只想存儲統一的數據類型,怎麼做嘞,那就搞個檢查裝置(就是泛型),起到一個過濾數據的作用,但是你這檢查裝置只是起到一個檢查過濾的作用,並不影響我本身,舉個例子就是好比我要開個針對程序員的大會,選了一個酒店,那麼這個酒店目前只允許程序員進入,所以找個保安(泛型)站在門口,只允許程序員進入,不是程序員的不讓進,那麼在大會開始之前(編譯階段),保安會在門口把門,只讓程序員進,等到人員都到場了,那麼可以確定的是酒店裏都是程序員了,那麼保安此時的任務就結束了,然後保安就可以撤了(泛型擦除),然後我們就開始開會了(運行階段)

這就是泛型擦除了,咋樣,我說的夠明白嗎?也就是說啊,泛型就是在編譯階段做了一個檢查,在編譯階段,不符合你指定的類型的數據都會檢查報錯,比如下面的代碼:

ArrayList<String> stringArrayList = new ArrayList<>();

因爲指定了具體的泛型實參String,那麼你這裏就只能添加字符串,編譯階段是會檢查的,一旦你添加的不是字符串,它就會報錯,你看:


image.png


等你添加完畢,這個ArrayList裏面就都是字符串類型了,到了運行階段,這裏的泛型信息就被擦除了,沒泛型啥事了,也就是本身ArrayList啥都可以存儲,現在是加了個泛型,可以確保我存儲的都是同種類型的。


再舉個例子就是,有一座茅草屋,本來這個茅草屋誰都可以進去,但是現在規定(相當於加了泛型),身價一個億的才能進去,但是即使進去的都是身價一個億的,這個茅草屋還是原來那個茅草屋,它也不可能變成豪華別墅啊(只是舉例子,拒絕槓精)


除了擦除,還有個轉換,舉個例子也就很容易明白,看代碼:


image.png


這是我們之前自定義的一個簡單的泛型類,現在我們使用這個類:


image.png


我們這裏指定具體的泛型實參是String字符串類型,那麼這個時候,代碼的實際編譯階段,這個G就全部被替換成了String,也就是變成了這個樣子:


image.png


這就是一個類型的轉換了,說的簡單點就是你定義的泛型形參在編譯的階段會被全部替換成你實際指定的泛型實參。

總結

好了,限於文章的篇幅,關於泛型有些點並沒有詳細展開來講,或者有的點也沒講,對於知識的學習,是需要不斷的深入和反覆的迭代的,想要一次性把一個知識全部學完也是不可能的,只能說,需要不斷的學習,所以關於泛型的講解就到這了,下面我簡單說下我個人對泛型的一些理解吧,希望對你有錦上添花的作用。


其實我一直覺得泛型這個東西有點像保安,就是看大門的,按照你的規定,允許誰可以進,誰不可以進,當然,這裏的進不進就是可不可以存儲的問題了,比如集合,是否可以向其添加數據,這是在你給規定之後,而這個規定你可以制定的多種多樣,這麼一來,就靈活多變了,其實關於泛型吧,剛開始理解是一道坎,理解了就覺得通透了,但是理解了也不一定算是掌握了,後面看一些源碼,使用泛型的很多,可是你還是不一定懂,但是在理解了的前提下,你纔有可能讀懂那些源碼,學習就是這樣,需要不斷的迭代,反覆的打磨,不能停啊!


好了,泛型就說到這裏,以後會根據情況適當增加和修改內容,一篇好的文章一定是反覆修改出來的,也歡迎大家提出你的看法和建議,一起交流學習,文中若有不當之處,還望提出!

感謝閱讀

大學的時候選擇了自學Java,工作了發現吃了計算機基礎不好的虧,學歷不行這是沒辦法的事,只能後天彌補,於是在編碼之外開啓了自己的逆襲之路,不斷的學習Java核心知識,深入的研習計算機基礎知識,所有心得全部書寫成文,整理成有目錄的PDF,持續原創,PDF在公衆號持續更新,如果你也不甘平庸,那就與我一起在編碼之外,不斷成長吧!

其實這裏不僅有技術,更有那些技術之外的東西,比如,如何做一個精緻的程序員,而不是“屌絲”,程序員本身就是高貴的一種存在啊,難道不是嗎?

非常歡迎你的加入,未來的日子,編碼之外,有你有我,一起做一個人不傻,錢很多,活得久的快樂的程序員吧!

回覆關鍵字“PDF”,獲取技術文章合集,已整理好,帶有目錄,歡迎一起交流技術!

另外回覆“慶哥”,看慶哥給你準備的驚喜大禮包,只給首次關注的你哦!

任何問題,可以加慶哥微信:H653836923,另外,我有個交流羣,我會***不定期在羣裏分享學習資源,不定時福利***,感興趣的可以說下我邀請你!

對了,如果你是個Java小白的話,也可以加我微信,我相信你在學習的過程中一定遇到不少問題,或許我可以幫助你,畢竟我也是過來人了!

在這裏插入圖片描述

感謝各位大大的閱讀🥰

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章