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