1. 程式人生 > >學員優秀博文賞析:泛型萬用字元及約束

學員優秀博文賞析:泛型萬用字元及約束

       最課程師徒班的同學正在紅紅火火的學習中。彷彿、應該、必須,到了跟大家階段性彙報成果的時候了。為什麼,因為畢竟當時把師徒班說的那麼好,就業班的同學該要鬧革命了。

       師徒班相較於就業班,雖然課程內容和總量完全一樣,但學員的學習過程掌握了更多的主動性。而檢驗主動性一個重要的標準,除了日常的作業和任務,就是學員們的部落格了。我們要求學員必須每週一篇博文。可以說,看學員部落格的過程,就可以知道大家的成長有多麼大了。

       說的這麼好,來,給看看唄。

       好滴。我們以後會陸續放出學員的優秀部落格。看部分同學的部落格,我都要怕怕了,怕很快我都要教不了他們了。長江後浪推前浪,一浪更比一浪浪~~~

       那麼好,開篇是誰?開篇難道不應該選一位極具geek氣息的同學(diaosi)嗎?到底是geek還是diaosi,你們來評判:

       哦,不不,帥氣就要露出來,怎能徒留背多芬:

       我們劉同學的這篇部落格名為:《對Java萬用字元的個人理解(以集合為例)》。可以說,初學者能將泛型萬用字元及約定理解到這種程度是很不容易的。不信,你去看看身邊的開發者,關於這塊的概念,多數工作了多年的開發者可能都沒我們的小劉同學理解的深刻。並且,劉同學一開始就不滿足僅限於日常體系的學習,很早就去關注了一些優秀的程式設計資源,比如阿里的編碼規範(本文中也有體現的)。

       咳咳,就業班的同學們,我馬上就要把師徒班的若干成功經驗應用到你們的頭上來了哦。當然,這也意味著你們將會犧牲更多的休息時間來完成作業和任務。不過,為了拿薪水更高的offer,一切都是值得的。

       華麗的分割線,以下是劉同學部落格原文:

=====================================================================================================================================

Java萬用字元的個人理解(以集合為例)

前言

       最近在學習Java,當學到了泛型的萬用字元時,不是很理解PECS(Producer Extends Consumer Super)原則,以及<? extends E> 不能使用add方法和<? super E> 不能使用get方法(注意:僅能使用Object o = list.get(0);取得是Object物件),所以我對它進行了學習和理解,這篇博文用了簡單通俗的方法去講解add和get在萬用字元中的使用場景以及PECS原則。可能本人的水平有限,如果我的理解有誤或者內容錯誤,歡迎指出來,我好進行及時修改。

一、什麼是泛型萬用字元

<一>簡單定義泛型統配符

1. 在瞭解泛型的統配符之前,我們先了解下什麼是泛型,泛型是一種包含型別引數的類,值得注意的一點是這裡的型別必須是引用資料型別,而且放在尖括號< >內,這裡引進了型別引數,將類直接作為了引數。

2. 那麼是什麼泛型統配符呢,我沒有找到定義,所以我自己給它下了個定義。泛型萬用字元是在泛型的使用中,用來表示對泛型型別進行類型範圍限定的特殊符號。這裡用萬用字元就是為了表明要輸入的型別要在一定範圍之內,說的通俗一些其實就是一個型別取值範圍,而最大值是Object這是確定的。

<二>泛型萬用字元的分類

1. <?>:無限萬用字元,可以在?中放入裡放入任何引用資料型別,用來接收任意引用資料型別。

2. <? extends E>:這個表明的是萬用字元的上界,通俗講就如同取值範圍中的負無窮到E,即小於等於E的所有型別, 因為E是最大的型別(最大可以達到Object),表明可以輸入所有的E的子類和E,等下會進行細緻的講解。

3. <? super E>:這個表明的是萬用字元的下界,通俗講其取值範圍就是E到最大值Object(因為Object是所有類的基類),就是大於等於E,小於等於Object類。

注意:這裡能制定上界或者下界,但是不能同時制定,然後<? extends E>中的extends不一定表示類與類的繼承還可以表示實現的關係,然後萬用字元一般是用在方法的形參宣告和方法呼叫上,無法用於定義類和介面中。

二、泛型萬用字元講解

 <一>萬用字元的使用以及程式碼演示

1.無限萬用字元<?>的使用:可以傳入任何引用資料型別

A 在呼叫方法時使用?萬用字元的過程中無法使用add方法。

原因分析:因為萬用字元?代表任意的資料型別,但是當我們呼叫的時候或者用在方法的宣告上,其實這個時候還是沒有給?萬用字元一個指定的引用資料型別,那麼Java出於安全起見,就不可能允許新增元素。

B 以上的add方法雖然無法呼叫,add<null>是例外。

原因分析:因為null可以給任意引用資料型別賦值,代表任意引用資料,但是很容易引起NullPointerException。

C 注意使用List<?>和List<Object>當作形參時的作用不能等同,比如當傳入List<Integer>時List<?>可以接收,但是List<Object>無法接收。

原因分析:因為?代表任何引數型別可以接收,但是List<Object>中雖然Object是所有子類的父類,但是List<Object>不是List<Integer>的父類,List<Object>是ArrayList<Object>等類的父類,這就是為什麼泛型前後要一致的原因,從陣列的角度去理解集合就比如Object[ ] arr不是Integer[ ] arr1的父類。

2.上界萬用字元<? extends E>的使用:可以傳入E和E的子類

A <? extends E>作為形參時例如List<? extends E>可以使用集合的get方法來獲取E或者E型別本身的元素。

原因分析:當我們用get方法時我們其實是在獲取集合裡內部的元素,但是我們的集合的資料型別還沒有確定,但是我們可以獲得一些明確的已知條件,那就是在<? extends E>中最大的型別是E,而且這個E最大是Object,所以我們可以利用這一點,那麼我們就可以清楚地瞭解到該集合裡面的獲取的元素肯定是E或者Object的子類,他們的範圍肯定小於E或者Object,那麼我們就可以用Object和E這兩個範圍比集合裡面的元素大的類去接收集合裡面的元素。(注:可能略顯囉嗦但是我就是想解釋清楚。)

B 在使用上界萬用字元時,無法呼叫add方法來新增非null的元素。

原因分析:由於上面已經說得很清楚了,<? extends E>作為形參時例如List<? extends E>這時最大型別是E和Object,但是我們不清楚最小的型別是什麼,因為此時?這個萬用字元沒有被賦值,我們呼叫add方法是要新增集合元素或者集合元素的子類,但是我們沒法明確肯定該集合元素型別,或者比該集合元素範圍更小的子類,那麼Java就不會允許新增元素。

3.下界萬用字元<? super E>的使用:可以傳入E或者E的父類

A 在使用下界萬用字元時,無法使用get方法獲取Object以外的元素,或者需要向下轉型,但是可能出現ClassCastException的異常。

原因分析:上界萬用字元,在使用get方法的時候,此時型別沒有明確還是問號?我們只能明確其最大父類或者介面時,我們才能接收,但是我們只能明白<? super E>作為形參時例如List<? super E>時,只能明確Object是最大父類,其他的一概不知,所以只能Object o = list.get(0)。

B 可以使用集合的add方法新增E或者E的子類。

原因分析:上界萬用字元已經解釋很清楚了,add方法新增元素時,?型別不確定就要明確該?型別的最小子類,只要比可能存在的最小子類或者子介面小的任意引用資料型別的物件,我們都可以將其新增,而下界萬用字元<? super E>當作形參時例如List<? super E>,此時E就是最小子類,此時add方法可以新增E或者E的父類或者介面。

<二>對PECS原則的解讀

1.什麼是PECS原則?

PECS是Producer Extends Consumer Super的遞迴縮寫,是Java中使用泛型萬用字元的原則。

2.阿里巴巴的萬用字元使用規約

泛型萬用字元<? extends T>來接收返回的資料,此寫法的泛型集合不能使用 add 方法,而 < ? super T> 不能使用 get 方法,做為介面呼叫賦值時易出錯。

說明:擴充套件說一下 PECS<Producer Extends Consumer Super> 原則:第一、頻繁往外讀取內容的,適合用<? extends E>。第二、經常往裡插入的,適合用<? super E> 。

3.對PECS原則的簡單解讀

字面意思是生產者要被繼承要被當作上界萬用字元<? extends E>的上界E,消費者要繼承其他類要被當成下界萬用字元<? super E>的下界E,再借助下阿里巴巴的泛型開發規約去理解下,應該就是當這個被傳入的型別需要進行很多get操作獲取資料的話,那麼請使用上界萬用字元這時這個上界就如同生產者一樣,因為它能被不斷get到,而當需要不斷進行add方法新增資料的話,請使用下界萬用字元這時這個下界就如同消費者一樣,因為它不斷地索取,因為我們在不斷地add元素給它。

再一次的分割線

===========================================================

2:師徒班持續招生中,想成為像劉同學一樣的優秀學員,請來這裡報名:http://www.zuikc.com

相關推薦

學員優秀賞析字元約束

       最課程師徒班的同學正在紅紅火火的學習中。彷彿、應該、必須,到了跟大家階段性彙報成果的時候了。為什麼,因為畢竟當時把師徒班說的那麼好,就業班的同學該要鬧革命了。        師徒班相較於就業班,雖然課程內容和總量完全一樣,但學員的學習過程掌握了更多的主動性。而檢驗主動性一個重要的標準,除了

學員優秀賞析雙基準快速排序實現

       我一般是不會去主動碰演算法問題的。上學的時候一個演算法複雜度就把我搞煩了,還想讓我去搞演算法本身?我是這麼安慰自己的:反正寫CRUD又不需要演算法,這輩子都不需要演算法的。好吧,其實我是一直不肯承認,不去動演算法的原因只有三個字:因為笨!        所以你去看,一般招演算法工程師的都是大廠

java5-字元

如果有兩個類: Shape類 public class Shape{ //價錢 private String area; } Square類 public class Square extends Shape{ //價錢 pri

java基礎-/字元

泛型 泛型的意義: a:可以對型別進行自動檢查。 並不是替換,只是編譯期間進行檢查。 b:自動對型別進行轉換。 泛型到底是怎麼編譯的? 型別的擦除機制:》向上擦除》Object(最高到) 在編譯器編譯期間,把泛型全部擦除為object型別。 用jmap命

java遺珠之字元

我們在之前說過明確指定了泛型型別的引數之後,會把引數限制的很嚴格,萬用字元的作用就是放寬這種限制,有上限有界萬用字元<? extends A>,下限有界萬用字元<? extends B>,無界萬用字元<?>。上限有界和無界經常

Java——字元

萬用字元泛型在使用泛型特殊的場景下用到; 比如把泛型物件作為方法引數傳入方法的時候,就用到萬用字元泛型; package Month01.Day05.Demo02; import Month01.Day05.Demo01.Cat; import Month01.Day05.Demo01.D

javaSE——字元介面、型別擦出

一、萬用字元 1.萬用字元的概念 前面我們學習的泛型都已經解決了很多問題了,但是我們在使用的時候還是指定了型別的。比如泛型類,我們在建立這個類的物件的時候就指定了是什麼型別,然後就只能建立這個型別的物件,那麼我們有時候想要建立任意型別的物件的時候我們可以使用萬用字元。 1.1無解萬用字元"?

關於字元邊界的疑惑解疑

<? extends someclass>為什麼可以get而不能set? void set(? extends someclass); ? extends someclass get();    我們使用萬用字元通常是希望某一個例項可以向上轉型 例: List&

三句話總結JAVA字元(PECS)

在JAVA的泛型集合中,預設都可以新增null,除此以外,還有以下三條規則。 1. “?”不能新增元素 以“?”宣告的集合,不能往此集合中新增元素,所以它只能作為生產者(亦即它只能被迭代),如下: List<?> names = Lis

Java 字元?解惑

T  有型別 ?  未知型別 一、萬用字元的上界 既然知道List<Cat>並不是List<Anilmal>的子型別,那就需要去尋找替他解決的辦法, 是AnimalTrianer.act()方法變得更為通用(既可以接受List<Anima

Java 字元解釋

前言 最近看Rxjava retrofit 中到處都是泛型型別定義,不得不重新整理一下資料,簡單介紹,滿足基本理解使用。 定義什麼是泛型? 泛型,即“引數化型別”。一提到引數,最熟悉的就是定義方法時有形參,然後呼叫此方法時傳遞實參。那麼引數化型別怎麼理

--字元的上下限

##泛型 ####泛型概述   泛型:可以在類或者方法當中預支的使用未知的資料型別。 備註:一般在建立物件的時候,將未知的資料型別確定為具體的資料型別,當沒有指定泛型時,預設型別為Object型別。 ####使用泛型的好處   避免了型別轉換的麻煩,儲存的是什麼樣的資料型別,取出的就是什麼樣的資料型

第一次作業閱讀優秀感想

span pan 衡量 試題 工具 時代 計劃 不想 解決問題 我是一只鹹魚 不想承認 也不能否認不要同情我笨 又誇我天真 還夢想著翻身鹹魚就算翻身 還是只鹹魚 輸得也誠懇至少到最後 我還有鹹魚 不腐爛的自尊我沒有任何天分 我卻有夢的天真我是傻 不是蠢我將會證明 用我的

第一次作業學習計算機與對優秀的感想

完成 一次 解決 信心 ont 未知數 努力學習 clas 了吧 作業概要: 第一部分:我與計算機 1結緣計算機 2在計算機系學習 3未來規劃 第二部分:優秀博文感想 1閱讀優秀博文寫出自己的感想與見解 第一部分:我與計算機 1結緣計算機 1你為什麽選擇計算機專

第一次作業閱讀優秀有感

讀書 規劃 很好 絲毫 hello mooc平臺 努力 自然 深入 結緣計算機 初時,我幻想的計算機專業大概是昏暗的機房裏一群不知面貌的學生和滿屏的滾動的代碼的黑客技術。談不上熱愛計算機專業,只是迷茫不知所選,奔著就業熱點填報了計算機專業。可以說在接受大學課程之前,只能

第一次作業閱讀優秀談感想

.com 但是 結構 tips 其余 應對 。。 初學者 不同 第一次作業:閱讀優秀博文談感想 第一部分:結緣計算機 我還記得2002年我家購買了聯想的一臺液晶屏機子,當時父母也是非常激動還專門去買了一套電腦桌設備,我的哥哥也是用一款《紅色警戒》帶我入了電腦遊戲的坑,當

第1次作業閱讀優秀有感

培養 大學生活 實現 機器 有關 寫代碼 計算機 都是 book 第一部分:結緣計算機 你為什麽選擇計算機專業?你認為你的條件如何?和這些博主比呢?

Java的定義(類、接口、對象)、使用、繼承

們的 hashmap rgs println 運行 報錯 collect arr param 地址 http://blog.csdn.net/lirx_tech/article/details/51570138 1. 設計泛型的初衷: 1) 主要是為了解決Jav

Java基礎

ret 原來 不能 使用 自定義泛型 編程 讀取數組 yum 實現   同樣是面試當中遇到的問題,在平常寫代碼的過程當中,經常有使用到泛型編程,比如用到的各種集合方式,如Arraylist、hashmap、List、等,都有使用到泛型。但是當面試官讓自己系統的介紹一下泛型編