原神一面:Java 泛型中的通配符 T,E,K,V,?,你确定都了解吗?
生活随笔
收集整理的這篇文章主要介紹了
原神一面:Java 泛型中的通配符 T,E,K,V,?,你确定都了解吗?
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
點(diǎn)擊上方 "編程技術(shù)圈"關(guān)注,?星標(biāo)或置頂一起成長(zhǎng)
后臺(tái)回復(fù)“大禮包”有驚喜禮包!
每日英文
Sometimes, the same thing, we can go to the comfort of others, but failed to?convince yourself.?
有時(shí)候,同樣的一件事情,我們可以去安慰別人,卻說服不了自己,確實(shí)是這樣的。
每日掏心話
時(shí)間在變,人也在變。生命那就是一團(tuán)欲望,欲望不滿足便痛苦。期望愈大,失望也便是愈大。
責(zé)編:樂樂?|?來自:juejin.im/post/5d5789d26fb9a06ad0056bd9
編程技術(shù)圈(ID:study_tech)第 1189?次推文
往日回顧:955 不加班的公司名單!2021 最新版!
??? ?
? ?正文? ?
前言泛型帶來的好處泛型中通配符常用的 T,E,K,V,??無界通配符上界通配符 < ? extends E>下界通配符 < ? super E>?和 T 的區(qū)別Class<T>和?Class<?>區(qū)別小結(jié)前言Java 泛型(generics)是 JDK 5 中引入的一個(gè)新特性, 泛型提供了編譯時(shí)類型安全檢測(cè)機(jī)制,該機(jī)制允許開發(fā)者在編譯時(shí)檢測(cè)到非法的類型。 泛型的本質(zhì)是參數(shù)化類型,也就是說所操作的數(shù)據(jù)類型被指定為一個(gè)參數(shù)。 泛型帶來的好處在沒有泛型的情況的下,通過對(duì)類型 Object 的引用來實(shí)現(xiàn)參數(shù)的“任意化”,“任意化”帶來的缺點(diǎn)是要做顯式的強(qiáng)制類型轉(zhuǎn)換,而這種轉(zhuǎn)換是要求開發(fā)者對(duì)實(shí)際參數(shù)類型可以預(yù)知的情況下進(jìn)行的。對(duì)于強(qiáng)制類型轉(zhuǎn)換錯(cuò)誤的情況,編譯器可能不提示錯(cuò)誤,在運(yùn)行的時(shí)候才出現(xiàn)異常,這是本身就是一個(gè)安全隱患。 那么泛型的好處就是在編譯的時(shí)候能夠檢查類型安全,并且所有的強(qiáng)制轉(zhuǎn)換都是自動(dòng)和隱式的。 public?class?GlmapperGeneric<T>?{private?T?t;public?void?set(T?t)?{?this.t?=?t;?}public?T?get()?{?return?t;?}public?static?void?main(String[]?args)?{//?do?nothing}/***?不指定類型*/public?void?noSpecifyType(){GlmapperGeneric?glmapperGeneric?=?new?GlmapperGeneric();glmapperGeneric.set("test");//?需要強(qiáng)制類型轉(zhuǎn)換String?test?=?(String)?glmapperGeneric.get();System.out.println(test);}/***?指定類型*/public?void?specifyType(){GlmapperGeneric<String>?glmapperGeneric?=?new?GlmapperGeneric();glmapperGeneric.set("test");//?不需要強(qiáng)制類型轉(zhuǎn)換String?test?=?glmapperGeneric.get();System.out.println(test);} }上面這段代碼中的 specifyType 方法中 省去了強(qiáng)制轉(zhuǎn)換,可以在編譯時(shí)候檢查類型安全,可以用在類,方法,接口上。 泛型中通配符我們?cè)诙x泛型類,泛型方法,泛型接口的時(shí)候經(jīng)常會(huì)碰見很多不同的通配符,比如 T,E,K,V 等等,這些通配符又都是什么意思呢? 常用的 T,E,K,V,?本質(zhì)上這些個(gè)都是通配符,沒啥區(qū)別,只不過是編碼時(shí)的一種約定俗成的東西。比如上述代碼中的 T ,我們可以換成 A-Z 之間的任何一個(gè) 字母都可以,并不會(huì)影響程序的正常運(yùn)行,但是如果換成其他的字母代替 T ,在可讀性上可能會(huì)弱一些。通常情況下,T,E,K,V,?是這樣約定的: ?表示不確定的 java 類型T (type) 表示具體的一個(gè)java類型K V (key value) 分別代表java鍵值中的Key ValueE (element) 代表Element?無界通配符先從一個(gè)小例子看起,原文在 這里 。 我有一個(gè)父類 Animal 和幾個(gè)子類,如狗、貓等,現(xiàn)在我需要一個(gè)動(dòng)物的列表,我的第一個(gè)想法是像這樣的: List<Animal>?listAnimals但是老板的想法確實(shí)這樣的: List<??extends?Animal>?listAnimals為什么要使用通配符而不是簡(jiǎn)單的泛型呢?通配符其實(shí)在聲明局部變量時(shí)是沒有什么意義的,但是當(dāng)你為一個(gè)方法聲明一個(gè)參數(shù)時(shí),它是非常重要的。 static?int?countLegs?(List<??extends?Animal?>?animals?)?{int?retVal?=?0;for?(?Animal?animal?:?animals?){retVal?+=?animal.countLegs();}return?retVal; }static?int?countLegs1?(List<?Animal?>?animals?){int?retVal?=?0;for?(?Animal?animal?:?animals?){retVal?+=?animal.countLegs();}return?retVal; }public?static?void?main(String[]?args)?{List<Dog>?dogs?=?new?ArrayList<>();//?不會(huì)報(bào)錯(cuò)countLegs(?dogs?);//?報(bào)錯(cuò)countLegs1(dogs); }當(dāng)調(diào)用 countLegs1 時(shí),就會(huì)飄紅,提示的錯(cuò)誤信息如下: 所以,對(duì)于不確定或者不關(guān)心實(shí)際要操作的類型,可以使用無限制通配符(尖括號(hào)里一個(gè)問號(hào),即 <?> ),表示可以持有任何類型。像 countLegs 方法中,限定了上屆,但是不關(guān)心具體類型是什么,所以對(duì)于傳入的 Animal 的所有子類都可以支持,并且不會(huì)報(bào)錯(cuò)。而 countLegs1 就不行。 上界通配符 < ? extends E>上屆:用 extends 關(guān)鍵字聲明,表示參數(shù)化的類型可能是所指定的類型,或者是此類型的子類。 在類型參數(shù)中使用 extends 表示這個(gè)泛型中的參數(shù)必須是 E 或者 E 的子類,這樣有兩個(gè)好處: 如果傳入的類型不是 E 或者 E 的子類,編譯不成功泛型中可以使用 E 的方法,要不然還得強(qiáng)轉(zhuǎn)成 E 才能使用private?<K?extends?A,?E?extends?B>?E?test(K?arg1,?E?arg2){E?result?=?arg2;arg2.compareTo(arg1);//.....return?result; }類型參數(shù)列表中如果有多個(gè)類型參數(shù)上限,用逗號(hào)分開 下界通配符 < ? super E>下界: 用 super 進(jìn)行聲明,表示參數(shù)化的類型可能是所指定的類型,或者是此類型的父類型,直至 Object 在類型參數(shù)中使用 super 表示這個(gè)泛型中的參數(shù)必須是 E 或者 E 的父類。 搜索后端架構(gòu)師公眾號(hào)回復(fù)“架構(gòu)整潔”,送你一份驚喜禮包。 private?<T>?void?test(List<??super?T>?dst,?List<T>?src){for?(T?t?:?src)?{dst.add(t);} }public?static?void?main(String[]?args)?{List<Dog>?dogs?=?new?ArrayList<>();List<Animal>?animals?=?new?ArrayList<>();new?Test3().test(animals,dogs); } //?Dog?是?Animal?的子類 class?Dog?extends?Animal?{}dst 類型 “大于等于” src 的類型,這里的“大于等于”是指 dst 表示的范圍比 src 要大,因此裝得下 dst 的容器也就能裝 src 。 ?和 T 的區(qū)別?和 T 都表示不確定的類型,區(qū)別在于我們可以對(duì) T 進(jìn)行操作,但是對(duì) ?不行,比如如下這種 : //?可以 T?t?=?operate();//?不可以 ?car = operate();簡(jiǎn)單總結(jié)下: T 是一個(gè) 確定的 類型,通常用于泛型類和泛型方法的定義,?是一個(gè) 不確定 的類型,通常用于泛型方法的調(diào)用代碼和形參,不能用于定義類和泛型方法。 區(qū)別1:通過 T 來 確保 泛型參數(shù)的一致性//?通過?T?來?確保?泛型參數(shù)的一致性 public?<T?extends?Number>?void test(List<T>?dest,?List<T>?src)//通配符是?不確定的,所以這個(gè)方法不能保證兩個(gè)?List?具有相同的元素類型 public?void test(List<??extends?Number>?dest,?List<??extends?Number>?src)像下面的代碼中,約定的 T 是 Number 的子類才可以,但是申明時(shí)是用的 String ,所以就會(huì)飄紅報(bào)錯(cuò)。 不能保證兩個(gè) List 具有相同的元素類型的情況 GlmapperGeneric<String>?glmapperGeneric?=?new?GlmapperGeneric<>(); List<String>?dest?=?new?ArrayList<>(); List<Number>?src?=?new?ArrayList<>(); glmapperGeneric.testNon(dest,src);上面的代碼在編譯器并不會(huì)報(bào)錯(cuò),但是當(dāng)進(jìn)入到 testNon 方法內(nèi)部操作時(shí)(比如賦值),對(duì)于 dest 和 src 而言,就還是需要進(jìn)行類型轉(zhuǎn)換。 區(qū)別2:類型參數(shù)可以多重限定而通配符不行使用 & 符號(hào)設(shè)定多重邊界(Multi Bounds),指定泛型類型 T 必須是 MultiLimitInterfaceA 和 MultiLimitInterfaceB 的共有子類型,此時(shí)變量 t 就具有了所有限定的方法和屬性。對(duì)于通配符來說,因?yàn)樗皇且粋€(gè)確定的類型,所以不能進(jìn)行多重限定。 區(qū)別3:通配符可以使用超類限定而類型參數(shù)不行類型參數(shù) T 只具有 一種 類型限定方式: T?extends?A但是通配符 ? 可以進(jìn)行 兩種限定: ??extends?A ??super?AClass<T>和?Class<?>區(qū)別前面介紹了 ?和 T 的區(qū)別,那么對(duì)于,Class<T>和?<Class<?>又有什么區(qū)別呢?Class<T>和?Class<?> 最常見的是在反射場(chǎng)景下的使用,這里以用一段發(fā)射的代碼來說明下。 //?通過反射的方式生成??multiLimit //?對(duì)象,這里比較明顯的是,我們需要使用強(qiáng)制類型轉(zhuǎn)換 MultiLimit?multiLimit?=?(MultiLimit) Class.forName("com.glmapper.bridge.boot.generic.MultiLimit").newInstance();對(duì)于上述代碼,在運(yùn)行期,如果反射的類型不是 MultiLimit 類,那么一定會(huì)報(bào) java.lang.ClassCastException 錯(cuò)誤。 對(duì)于這種情況,則可以使用下面的代碼來代替,使得在在編譯期就能直接 檢查到類型的問題: Class<T>在實(shí)例化的時(shí)候,T 要替換成具體類。Class<?>它是個(gè)通配泛型,? 可以代表任何類型,所以主要用于聲明時(shí)的限制情況。比如,我們可以這樣做申明: //?可以 public?Class<?>?clazz; //?不可以,因?yàn)?T?需要指定類型 public?Class<T>?clazzT;所以當(dāng)不知道定聲明什么類型的 Class 的時(shí)候可以定義一 個(gè)Class<?>。 那如果也想?public Class<T> clazzT;這樣的話,就必須讓當(dāng)前的類也指定 T , public?class?Test3<T>?{public?Class<?>?clazz;//?不會(huì)報(bào)錯(cuò)public?Class<T>?clazzT;小結(jié)本文零碎整理了下 JAVA 泛型中的一些點(diǎn),不是很全,僅供參考。如果文中有不當(dāng)?shù)牡胤?#xff0c;歡迎指正。PS:歡迎在留言區(qū)留下你的觀點(diǎn),一起討論提高。如果今天的文章讓你有新的啟發(fā),歡迎轉(zhuǎn)發(fā)分享給更多人。 版權(quán)申明:內(nèi)容來源網(wǎng)絡(luò),版權(quán)歸原創(chuàng)者所有。除非無法確認(rèn),我們都會(huì)標(biāo)明作者及出處,如有侵權(quán)煩請(qǐng)告知,我們會(huì)立即刪除并表示歉意。謝謝!歡迎加入后端架構(gòu)師交流群,在后臺(tái)回復(fù)“學(xué)習(xí)”即可。猜你還想看 阿里、騰訊、百度、華為、京東最新面試題匯集 注意!某知名國(guó)產(chǎn)軟件被曝?cái)y帶木馬病毒漫畫:為什么程序猿 996 會(huì)猝死,而企業(yè)家 007 卻不會(huì)?大一新生開發(fā)的小工具火了,網(wǎng)友:我好菜BAT等大廠Java面試經(jīng)驗(yàn)總結(jié) 別找了,想獲取 Java大廠面試題學(xué)習(xí)資料 掃下方二維碼回復(fù)「手冊(cè)」就好了嘿,你在看嗎?總結(jié)
以上是生活随笔為你收集整理的原神一面:Java 泛型中的通配符 T,E,K,V,?,你确定都了解吗?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 基于java点播影院运营系统计算机毕业设
- 下一篇: 《程序员转行之光速入门产品经理》