www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當前位置:首頁 > 公眾號精選 > 架構(gòu)師社區(qū)
[導讀]來源:https://juejin.cn/post/6844903917835419661|前言Java泛型(generics)是JDK5中引入的一個新特性,泛型提供了編譯時類型安全檢測機制,該機制允許開發(fā)者在編譯時檢測到非法的類型。泛型的本質(zhì)是參數(shù)化類型,也就是說所操作的數(shù)據(jù)類...

| 前言

Java 泛型(generics)是 JDK 5 中引入的一個新特性, 泛型提供了編譯時類型安全檢測機制,該機制允許開發(fā)者在編譯時檢測到非法的類型。


泛型的本質(zhì)是參數(shù)化類型,也就是說所操作的數(shù)據(jù)類型被指定為一個參數(shù)。


| 泛型帶來的好處


在沒有泛型的情況的下,通過對類型 Object 的引用來實現(xiàn)參數(shù)的“任意化”,“任意化”帶來的缺點是要做顯式的強制類型轉(zhuǎn)換,而這種轉(zhuǎn)換是要求開發(fā)者對實際參數(shù)類型可以預知的情況下進行的。對于強制類型轉(zhuǎn)換錯誤的情況,編譯器可能不提示錯誤,在運行的時候才出現(xiàn)異常,這是本身就是一個安全隱患。


那么泛型的好處就是在編譯的時候能夠檢查類型安全,并且所有的強制轉(zhuǎn)換都是自動和隱式的。


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");
// 需要強制類型轉(zhuǎn)換
String test = (String) glmapperGeneric.get();
System.out.println(test);
}

/**
* 指定類型
*/

public void specifyType(){
GlmapperGenericglmapperGeneric = new GlmapperGeneric();
glmapperGeneric.set("test");
// 不需要強制類型轉(zhuǎn)換
String test = glmapperGeneric.get();
System.out.println(test);
}
}
上面這段代碼中的 specifyType 方法中 省去了強制轉(zhuǎn)換,可以在編譯時候檢查類型安全,可以用在類,方法,接口上。


| 泛型中通配符


我們在定義泛型類,泛型方法,泛型接口的時候經(jīng)常會碰見很多不同的通配符,比如 T,E,K,V 等等,這些通配符又都是什么意思呢?


常用的 T,E,K,V,?

本質(zhì)上這些個都是通配符,沒啥區(qū)別,只不過是編碼時的一種約定俗成的東西。比如上述代碼中的 T ,我們可以換成 A-Z 之間的任何一個 字母都可以,并不會影響程序的正常運行,但是如果換成其他的字母代替 T ,在可讀性上可能會弱一些。通常情況下,T,E,K,V,?是這樣約定的:


  • ?表示不確定的 java 類型
  • T (type) 表示具體的一個java類型
  • K V (key value) 分別代表java鍵值中的Key Value
  • E (element) 代表Element

?無界通配符

先從一個小例子看起 。


我有一個父類 Animal 和幾個子類,如狗、貓等,現(xiàn)在我需要一個動物的列表,我的第一個想法是像這樣的:


List listAnimals
但是老板的想法確實這樣的:


List listAnimals
為什么要使用通配符而不是簡單的泛型呢?通配符其實在聲明局部變量時是沒有什么意義的,但是當你為一個方法聲明一個參數(shù)時,它是非常重要的。


static int countLegs (List 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) {
Listdogs = new ArrayList<>();
// 不會報錯
countLegs( dogs );
// 報錯
countLegs1(dogs);
}
當調(diào)用 countLegs1 時,就會飄紅,提示的錯誤信息如下:


聊一聊Java?泛型通配符?T,E,K,V,?所以,對于不確定或者不關心實際要操作的類型,可以使用無限制通配符(尖括號里一個問號,即 ),表示可以持有任何類型。像 countLegs 方法中,限定了上界,但是不關心具體類型是什么,所以對于傳入的 Animal 的所有子類都可以支持,并且不會報錯。而 countLegs1 就不行。


上界通配符 < ? extends E>

上屆:用 extends 關鍵字聲明,表示參數(shù)化的類型可能是所指定的類型,或者是此類型的子類。


在類型參數(shù)中使用 extends 表示這個泛型中的參數(shù)必須是 E 或者 E 的子類,這樣有兩個好處:


  • 如果傳入的類型不是 E 或者 E 的子類,編譯不成功
  • 泛型中可以使用 E 的方法,要不然還得強轉(zhuǎn)成 E 才能使用
private E test(K arg1, E arg2){
E result = arg2;
arg2.compareTo(arg1);
//.....
return result;
}
類型參數(shù)列表中如果有多個類型參數(shù)上限,用逗號分開


下界通配符 < ? super E>

下界: 用 super 進行聲明,表示參數(shù)化的類型可能是所指定的類型,或者是此類型的父類型,直至 Object


在類型參數(shù)中使用 super 表示這個泛型中的參數(shù)必須是 E 或者 E 的父類。


private void test(List dest, List src)
像下面的代碼中,約定的 T 是 Number 的子類才可以,但是申明時是用的 String ,所以就會飄紅報錯。


聊一聊Java?泛型通配符?T,E,K,V,?不能保證兩個 List 具有相同的元素類型的情況


GlmapperGenericglmapperGeneric = new GlmapperGeneric<>();
Listdest = new ArrayList<>();
Listsrc = new ArrayList<>();
glmapperGeneric.testNon(dest,src);
上面的代碼在編譯器并不會報錯,但是當進入到 testNon 方法內(nèi)部操作時(比如賦值),對于 dest 和 src 而言,就還是需要進行類型轉(zhuǎn)換。


區(qū)別2:類型參數(shù)可以多重限定而通配符不行

聊一聊Java?泛型通配符?T,E,K,V,?使用
本站聲明: 本文章由作者或相關機構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
關閉
關閉