java中的強迫癥患者

java零基礎入門-高級特性篇(五) 泛型? 上

前面說集合的時候,有一個往List添加元素的方法add(E e),說這個 E 叫泛型,可以表示任何一種類型。為什么往集合添加元素的時候需要泛型?因為上一章的集合示例過于理想化,人為制造了一個前提,就是認為往集合里添加元素都是同樣的類型。但是理想很豐滿,現(xiàn)實很骨感,如果對于一個集合添加的元素沒有約束,可以隨意往一個集合里面放任何類型的對象,會發(fā)生意想不到的問題。

為什么有泛型


雙十一你剁手了沒?每到雙十一,我們唯一的目標就是清空購物車,拿起你的手機,買買買~好了,作為一個程序員,這里從代碼的眼光出發(fā),看看購物車這個神奇的東西。

首先有一個集合,就是購物車,用來放商品對象。商品的屬性有名稱,價格,類別。然后新建一個商品,再丟進購物車,我忘了看價格,需要拿出來看看價格,看如何實現(xiàn)。

購物車

為什么這個關鍵步驟需要進行強制轉(zhuǎn)換類型?你寫上面代碼的時候可以試試不強制轉(zhuǎn)會會發(fā)生什么。如果不轉(zhuǎn)換,cart.get(0)這個地方拿出的對象是Object類型,無法獲取到price這個屬性的值。不對呀!我放進去的明明就是一個商品類型Commodity呀,為什么拿出來的時候變成Object了?不好意思,購物車不夠智能,并不能記錄每一個你放進購物車的東西是什么類型,他只能通通當成Object處理了,因為Object是所有類型的父類,不管你放啥進購物車,他肯定是個Object。

這里雖然看個價格很麻煩,還要轉(zhuǎn)換類型,但是終歸能看到類型。但是接下來發(fā)生的情況就不那么簡單了。正當我開開心心買買買的時候,突然發(fā)現(xiàn),哎喲~不錯喲~居然有的商品還有贈品!真是開心的不得了。贈品的屬性有名稱,類別。看代碼。

贈品

先看運行結(jié)果是什么。

Exception in thread "main" java.lang.ClassCastException: com.java.lesson14.Present cannot be cast to com.java.lesson14.Commodity

at com.java.lesson14.Shopping2.main(Shopping2.java:24)

這是啥玩意?不是應該輸出兩個價格嗎?這個東西叫異常,異常就是程序發(fā)生了錯誤,程序給出的錯誤信息。看看錯誤信息說了啥,ClassCastException,這個異常叫做類型轉(zhuǎn)換異常。Present cannot be cast to?Commodity,意思是Present類型不能轉(zhuǎn)換成Commodity類型,最后一行是出現(xiàn)錯誤的位置,Shopping2.java:24 ,24行發(fā)生了類型轉(zhuǎn)換錯誤。

來看看24行發(fā)生了什么,為什么出現(xiàn)類型轉(zhuǎn)換錯誤。24行將第二個加入到集合的元素轉(zhuǎn)換成Commodity類型,原來往購物車添加東西的時候,第一個是商品,第二個是贈品,24行將贈品轉(zhuǎn)為商品類型,就發(fā)生了錯誤。

為什么寫代碼的時候不報錯呢?運行才報錯呢?因為我們只設置了一個購物車,沒有規(guī)定購物車里面放什么呀,沒有規(guī)定當然什么都可以放,扔個贈品進去也很正常啊。運行的時候,要從購物車里面將東西拿出來,上個例子看到,拿出來的時候是不知道這個東西是個什么類型的,統(tǒng)一認為是Object。完蛋,我不知道哪個要轉(zhuǎn)換成商品類型,哪個要轉(zhuǎn)換成贈品類型,類型轉(zhuǎn)換發(fā)生錯誤可想而知。

這里使用的是List集合,可以按照順序來判斷類型,但是換成了Set,那就是真的不知道要轉(zhuǎn)什么類型了。

問題出現(xiàn)了,往集合里面放東西,拿出來的時候可能會發(fā)生錯誤,集合沒有記錄我扔進去元素的類型,拿出來又只給我Object,這下如何是好?

現(xiàn)在,終于輪到本章主角隆重登場了。

泛型是什么

沒有泛型的時候,集合就是個強迫癥患者,什么強迫癥?元素類型不統(tǒng)一就不能清空購物車,不能清空購物車就渾身難受,心浮氣躁,上躥下跳。而泛型的出現(xiàn),恰恰治好了集合的強迫癥。為了能夠清空購物車,當我們新建購物車的時候,就立下字據(jù),這個購物車只能放商品,不是商品通通不讓放。如何實現(xiàn)?

List cart = new ArrayList();? ?//沒有立字據(jù),什么都可以放

List<Commodity> cart = new ArrayList<Commodity>();? //立字據(jù),只能放Commodity類型的東西進購物車

這里的<Commodity>就是泛型。表示這個集合只能放Commodity類型的元素。你敢放其他類型元素,我就敢報錯。

修改

一旦給集合加上了泛型,在編譯的時候,就會判斷元素類型是否允許加入到集合,就不會出現(xiàn)上面那種只有在運行期才知道類型不對的錯誤了。但是贈品不能添加到購物車怎么辦?總不能把贈品丟掉吧,舍不得呀,沒關系,把贈品變成商品就行,價格設置為0。

上面的例子有點小小的問題,但是我不打算改,正好拿來復習前面的知識點。一個屬性設置為常量需要在前面加上static和final這兩個關鍵字,并且變量名全部大寫。上面例子中這個常量其實是沒有起到作用的,因為在shopping3這個類中,將鉛筆這個贈品強制轉(zhuǎn)換到父類商品,調(diào)用getPrice()方法是獲取父類中的price屬性,并不是子類贈品里面這個設置為0的常量。如果要獲取子類價格這個常量0,需要修改2個地方。第一,Present類添加getPrice這個方法,返回常量PRICE。第二,Shopping3類強制轉(zhuǎn)換的時候,將第二個元素強制轉(zhuǎn)換為子類Present,這樣打印的時候使用的就是子類PRICE常量。

集合不加泛型是可以的,但是如果元素類型不一致,強迫癥犯了渾身難受。所以建議使用集合的時候都要加上泛型,這樣不僅治好了強迫癥,還能夠使代碼更加健壯,不會有太多的隱患,不然bug滿天飛小心飯碗不保。

泛型的語法變化

在java5的時候,有了泛型治好了集合的強迫癥,List,Set,Map都可以使用泛型來規(guī)范元素的類型。但是有個缺點就是寫起來太啰嗦了。List和Set還好,Map寫起來真的是手要抽筋。

Map<String,Object> map = new HashMap<String,Object>();

是不是有個問題,在定義map的時候就寫了,我這個map元素的key-value類型是:key用String,value是Object,為什么在實現(xiàn)的時候還要再寫一遍?在java7之前,不好意思,你還真得老老實實寫一遍,但是java7的出現(xiàn),可以讓我們偷偷懶了。不需要在實現(xiàn)的時候再寫一遍泛型類型。

Map<String,Object> map = new HashMap<>();

后面只需要一對<>括號即可,java會根據(jù)前面的定義,自己來推斷這里的泛型是什么類型。是不是更先進更智能了。


集合里的泛型是泛型使用最廣泛的地方,除了治好了集合的強迫癥,泛型還有很多其他的用處,下期繼續(xù)。

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容