摘要:泛型類泛型類和普通類的區(qū)別就是類定義時,在類名后加上泛型聲明。泛型類的內(nèi)部成員方法就可以使用聲明的參數(shù)類型。
泛型是JDK 1.5的一項新特性,它的本質(zhì)是參數(shù)化類型(Parameterized Type),即所操作的數(shù)據(jù)類型在定義時被指定為一個參數(shù)。當(dāng)我們使用的時候給這個參數(shù)指定不同的對象類型,就可以處理不同的對象。這種參數(shù)類型可以用在類、接口和方法的創(chuàng)建中,分別稱為泛型類、泛型接口和泛型方法。
一、泛型實現(xiàn)方式泛型聲明方式:<占位符>
占位符有兩大類:
普通占位符,E, T, K, V一般是單字母大寫,表示接收特定的類型。
通用占位符,也叫通配符,占位符中包含“?”問號,表示接任意數(shù)據(jù)類型或者指定范圍數(shù)據(jù)類型。
泛型類泛型類和普通類的區(qū)別就是類定義時,在類名后加上泛型聲明。泛型類的內(nèi)部成員、方法就可以使用聲明的參數(shù)類型。泛型類最常見的用途就是作為容納不同數(shù)據(jù)類型的容器類,比如Java集合容器類。
class GenericClass泛型接口{ private T value; public T getValue() { return value; } public void setValue(T value) { this.value = value; } }
和泛型類一樣,泛型接口在接口名后添加泛型聲明,接口方法就可以直接使用聲明的參數(shù)類型。
實現(xiàn)類在實現(xiàn)泛型接口時需要指明具體的參數(shù)類型,不然默認類型是 Object,這就失去了泛型接口的意義。
interface genericInterface{ K getKey(); V getValue(); }
未指明類型的實現(xiàn)類,默認是 Object 類型:
class GenericClass implements genericInterface{ @Override public Object getKey() { return null; } @Override public Object getValue() { return null; } }
指明了類型的實現(xiàn):
class GenericClass implements genericInterface泛型方法{ @Override public String getKey() { return null; } @Override public Object getValue() { return null; } }
泛型方法指的是使用泛型的方法。如果這個方法所在的類是個泛型類,直接使用類聲明的參數(shù)類型。
如果這個方法所在的類不是泛型類或者他想要處理不同于泛型類所聲明的參數(shù)類型,這時候我們就需要使用泛型方法。即在方法前加入泛型聲明,方法就可以直接使用聲明的參數(shù)類型。
class GenericClass { private Object value; publicT getValue(){ return (T)value; } public void setValue(Object value){ this.value = value; } }
方法getValue()就是泛型方法,調(diào)用代碼如下:
GenericClass genericClass = new GenericClass(); genericClass.setValue(123); Integer value = genericClass.getValue();二、泛型的優(yōu)點 數(shù)據(jù)類型安全
泛型的主要目的通過參數(shù)類型檢查,提高JAVA程序數(shù)據(jù)類型的安全,提早發(fā)現(xiàn)錯誤,避免ClassCastException 異常發(fā)生。
List list = new ArrayList(); list.add("test generic"); list.add(123);// 注:123會轉(zhuǎn)換成Integer對象 list.add(null);
當(dāng)不實用泛型的時候,上面代碼的使用是被允許的,我們可以放入任何對象,當(dāng)我們按照某種對象類型去取數(shù)據(jù)就會出現(xiàn)ClassCastException 異常。
//Listlist = new ArrayList (); List list = new ArrayList(); list.add("test generic"); //list.add(123); list.add(null);
List是泛型接口,當(dāng)我們這樣使用的時候,“123”這個元素是不被允許使用的。
消除類型轉(zhuǎn)換當(dāng)我們不使用泛型時,每次取出集合中的元素都需要我們強制轉(zhuǎn)換成我們需要的元素。(Object->Class Type)。
List list = new ArrayList(); list.add("test generic"); String s = (String) list.get(0);
“test generic”存入list是一個Object的對象,取出來是我們需要轉(zhuǎn)換成我們要的字符串String類型。
Listlist = new ArrayList(); list.add("test generic"); String s = list.get(0);
使用泛型后list.get(0)中取出來的數(shù)據(jù)類型,就是我們存入時的String類型。
簡碼,提高效率通過泛型的應(yīng)用,做到了簡碼,而且JVM中類文件也相應(yīng)的減少。JVM幾乎沒有做任何的更改,所有的類型校驗,類型轉(zhuǎn)換都是在編譯器階段完成。
三、通配符 無限制通配符>定義時不關(guān)心或者不確定實際要操作的數(shù)據(jù)是什么類型,可以使用無限制通配符(尖括號里一個問號,即 > ),表示可以持有任何類型。
class GenericClass{ private T data; public T getData() { return data; } public void setData(T data) { this.data = data; } @Override public String toString() { return "GenericClass{" + "data=" + data + "}"; } }
泛型類定義
public static void print(GenericClass> context){ System.out.println(context); }
通配符定義的方法參數(shù)類型
GenericClassintegerGenericClass = new GenericClass<>(); integerGenericClass.setData(123); GenericClass stringGenericClass = new GenericClass<>(); stringGenericClass.setData("123"); print(integerGenericClass); print(stringGenericClass);
使用時?是一個萬能的類型,T只能是具體的類型
上界通配符 extends E>在類型參數(shù)中使用extends表示這個泛型中的參數(shù)必須是 E 或者 E 的子類,這樣有兩個好處:
如果傳入的類型不是E或者E的子類,編輯不成功
泛型中可以使用E的方法,要不然還得強轉(zhuǎn)成E才能使用
List extends Number> list = new ArrayList(){{add(new Integer(456));add(new Long(456L)); }}; list.add(null); //list.add(new Integer(123)); //list.add(new Long(123L)); System.out.println(list.size()); Number number = list.get(0);
當(dāng)使用上邊界通配符時,是不允許往里存數(shù)據(jù)的,不確定具體元素類型。
下界通配符 < ? super E>在類型參數(shù)中使用super表示這個泛型中的參數(shù)必須是E或者E的父類。
用于靈活寫入或比較,使得對象可以寫入父類型的容器,使得父類型的比較方法可以應(yīng)用于子類對象。
List super C> list = new ArrayList(){{add(new B()); add(new C());}}; list.add(null); list.add(new C()); list.add(new B()); //list.add(new A()); Object object = list.get(0);
C是B的子類,B是A的子類。當(dāng)使用下界通配符時,是允許存放E和E的子對象數(shù)據(jù)的,因為子類對象的引用可以賦值給父類對象的引用(頂級父類是Object),所以取出來的數(shù)據(jù)類型是Object.
四、總結(jié)在實例化的時候,就必須聲明泛型具體是一個什么類型。
使用泛型、通配符提高了代碼的復(fù)用性。
把一個對象分為聲明、使用兩部分的話。泛型側(cè)重于類型的聲明上代碼復(fù)用,通配符則側(cè)重于使用上的代碼復(fù)用。泛型用于定義內(nèi)部數(shù)據(jù)類型的不確定性,通配符則用于定義使用的對象類型不確定性。
如果類型參數(shù)在方法聲明中只出現(xiàn)一次,可以用通配符代替它。
不能同時聲明泛型通配符上界和下界。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/70631.html
摘要:動態(tài)代理個經(jīng)紀人如何代理個明星掘金在代理模式女朋友這么漂亮,你缺經(jīng)紀人嗎中我們用寶強的例子介紹了靜態(tài)代理模式的概念。掘金使用從頭創(chuàng)建一個,這種方法比較簡單。 動態(tài)代理:1 個經(jīng)紀人如何代理 N 個明星 - Android - 掘金在 代理模式:女朋友這么漂亮,你缺經(jīng)紀人嗎? 中我們用寶強的例子介紹了靜態(tài)代理模式的概念。 本來我的目的是通過大家耳熟能詳?shù)睦觼砑由罾斫?,但是有些網(wǎng)友指責(zé)...
摘要:之前,使用匿名類給蘋果排序的代碼是的,這段代碼看上去并不是那么的清晰明了,使用表達式改進后或者是不得不承認,代碼看起來跟清晰了。這是由泛型接口內(nèi)部實現(xiàn)方式造成的。 # Lambda表達式在《Java8實戰(zhàn)》中第三章主要講的是Lambda表達式,在上一章節(jié)的筆記中我們利用了行為參數(shù)化來因?qū)Σ粩嘧兓男枨?,最后我們也使用到了Lambda,通過表達式為我們簡化了很多代碼從而極大地提高了我們的...
摘要:利用前面所述的方法,這個例子可以用方法引用改寫成下面的樣子構(gòu)造函數(shù)引用對于一個現(xiàn)有構(gòu)造函數(shù),你可以利用它的名稱和關(guān)鍵字來創(chuàng)建它的一個引用。 第三章 Lambda表達式 函數(shù)式接口 函數(shù)式接口就是只定義一個抽象方法的接口,哪怕有很多默認方法,只要接口只定義了一個抽象方法,它就仍然是一個函數(shù)式接口。 常用函數(shù)式接口 showImg(https://segmentfault.com/img...
摘要:構(gòu)造器創(chuàng)建實例構(gòu)造器和方法的反射類不同點在于,可以創(chuàng)建實例,代碼如下所示。 上一篇文章介紹了反射的基本概念以及獲取類相關(guān)信息的反射API,這一章節(jié)主要記錄如何對類的成員進行操作的相關(guān)反射API。 操作類成員的類 反射API中提供了如下接口,用于對類的成員進行操作。 java.lang.reflect.Member 該接口主要有以下三個實現(xiàn)類,用于對類成員中的字段,方法和構(gòu)造器進行操作...
閱讀 3330·2021-11-23 09:51
閱讀 2459·2021-11-09 09:46
閱讀 1493·2019-08-30 15:54
閱讀 3140·2019-08-30 14:22
閱讀 2919·2019-08-29 12:40
閱讀 1644·2019-08-26 10:33
閱讀 1789·2019-08-23 17:09
閱讀 1565·2019-08-23 16:11