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