深入淺出理解Java泛型的使用
一、泛型的意義
二、泛型的使用
1.jdk 5.0新增特性
2.在集合中使用泛型:
總結(jié):
A.集合接口或集合類(lèi)在jdk5.0時(shí)都修改為帶泛型的結(jié)構(gòu)。
B.在實(shí)例化集合類(lèi)時(shí),可以指明具體的泛型類(lèi)型。
C.指明完以后,在集合類(lèi)或接口中凡是定義類(lèi)或接口時(shí),內(nèi)部結(jié)構(gòu)(比如:方法、構(gòu)造器、屬性等)使用類(lèi)的泛型的位置,
都指定為實(shí)例化的泛型類(lèi)型。比如:add(E e) --->實(shí)例化以后:add(Integer e)
D.注意點(diǎn):泛型的類(lèi)型必須是類(lèi),不能是基本數(shù)據(jù)類(lèi)型。需要用到基本數(shù)據(jù)類(lèi)型的位置,用包裝類(lèi)去替換
E.如果實(shí)例化時(shí),沒(méi)有指明泛型的類(lèi)型。默認(rèn)類(lèi)型為java.lang.Object類(lèi)型。
3.如何自定義泛型結(jié)構(gòu):泛型類(lèi)、泛型結(jié)構(gòu)、泛型方法
//在集合中使用泛型之前的情況: @Test public void test1(){ ArrayList list = new ArrayList(); //需求:存放學(xué)生的成績(jī) list.add(78); list.add(76); list.add(89); list.add(88); //問(wèn)題一:類(lèi)型不安全 list.add("Tom"); for(Object score : list){ //問(wèn)題二:強(qiáng)轉(zhuǎn)時(shí),可能出現(xiàn)ClassCateException int stuScore = (Integer)score; System.out.println(stuScore); } } //在集合中使用泛型的情況: @Test public void test2(){ ArrayList<Integer> list = new ArrayList<Integer>(); list.add(78); list.add(76); list.add(89); list.add(88); //編譯時(shí),就會(huì)進(jìn)行類(lèi)型檢查,保證數(shù)據(jù)的安全 // list.add("Tom"); //方式一: for(Integer score : list){ //避免了強(qiáng)轉(zhuǎn)操作 int stuScore = score; System.out.println(stuScore); } //方式二: Iterator<Integer> iterator = list.iterator(); while(iterator.hasNext()){ int stuScore = iterator.next(); System.out.println(stuScore); } } //在集合中使用泛型的情況:以HashMap為例 @Test public void test3(){ Map<String, Integer> map = new HashMap<String, Integer>(); map.put("Tom",87); map.put("Jerry",87); map.put("Jack",67); //泛型的嵌套 Set<Map.Entry<String, Integer>> entry = map.entrySet(); Iterator<Map.Entry<String, Integer>> iterator = entry.iterator(); while(iterator.hasNext()){ Map.Entry<String, Integer> entry1 = iterator.next(); String key = entry1.getKey(); Integer value = entry1.getValue(); System.out.println(key + "----" + value); } }
三、自定義泛型類(lèi)
1.泛型類(lèi)可能有多個(gè)參數(shù),此時(shí)應(yīng)將多個(gè)參數(shù)一起放在尖括號(hào)內(nèi)。比如:
<E1,E2,E3>
2.泛型類(lèi)的構(gòu)造器如下: public GenericClass (){}。
而下面是錯(cuò)誤的: public GenericClass < E >(){}
3.實(shí)例化后,操作原來(lái)泛型付置的結(jié)構(gòu)必須與指定的泛型類(lèi)型致。
4.泛型不同的引用不能相互賦值。
盡管在編譯時(shí) ArrayList < String >和 ArrayListslnteger 是兩種類(lèi)型,但是,在運(yùn)行時(shí)只有一個(gè) ArrayList 被加載到 JVM 中。
5.泛型如果不指定,將被探除,泛型對(duì)應(yīng)的類(lèi)型昀按照 Object 處理,但不等價(jià)于Object 。經(jīng)驗(yàn):泛型要使用路都用。要不用,一路都本要用。
6.如果泛型類(lèi)是一個(gè)按口或抽象類(lèi),則不可創(chuàng)建泛型類(lèi)的對(duì)象。
7.jdk1.7 ,泛的簡(jiǎn)化操作 ArrayList < Fruit > flist = new ArrayList<>();
8.泛型的指定中不能使用基本數(shù)據(jù)類(lèi)型,可以使用包裝類(lèi)替換。
1.關(guān)于自定義泛型類(lèi)、泛型接口:
@Test public void test1(){ //如果定義了泛型類(lèi),實(shí)例化沒(méi)有指明類(lèi)的泛型,則認(rèn)為此泛型類(lèi)型為Object類(lèi)型 //要求:如果大家定義了類(lèi)是帶泛型的,建議在實(shí)例化時(shí)要指明類(lèi)的泛型。 Order order = new Order(); order.setOrderT(123); order.setOrderT("ABC"); //建議:實(shí)例化時(shí)指明類(lèi)的泛型 Order<String> order1 = new Order<String>("OrderAA", 1001, "Order:AA"); order1.setOrderT("AA:hello"); } @Test public void test2(){ SubOrder sub1 = new SubOrder(); //由于子類(lèi)在繼承帶泛型的父類(lèi)時(shí),指明了泛型類(lèi)型。則實(shí)例化子類(lèi)對(duì)象時(shí),不再需要指明泛型。 sub1.setOrderT(1122); SubOrder1<String> sub2 = new SubOrder1<>(); sub2.setOrderT("order2..."); } //測(cè)試泛型方法 @Test public void test3(){ Order<String> order = new Order<>(); Integer[] arr = new Integer[]{1, 2, 3, 4}; //泛型方法在調(diào)用時(shí),指明泛型參數(shù)的類(lèi)型 List<Integer> list = order.copyFromArrayToList(arr); System.out.println(list);//[1, 2, 3, 4] }
自定義泛型類(lèi) public class Order<T> { String orderName; int orderId; //類(lèi)的內(nèi)部結(jié)構(gòu)就可以使用類(lèi)的泛型 T orderT; public Order(){}; public Order(String orderName,int orderId,T orderT){ this.orderName = orderName; this.orderId = orderId; this.orderT = orderT; } public T getOrderT(){ return orderT; } @Override public String toString() { return "Order{" + "orderName='" + orderName + '\'' + ", orderId=" + orderId + ", orderT=" + orderT + '}'; } public void setOrderT(T orderT){ this.orderT = orderT; } //泛型方法:在方法中出現(xiàn)了泛型的結(jié)構(gòu),翻新參數(shù)與類(lèi)的泛型參數(shù)沒(méi)有任何關(guān)系。 //換句話(huà)說(shuō),泛型方法所屬的類(lèi)是不是泛型類(lèi)都沒(méi)有關(guān)系。 //泛型方法,可以聲明為靜態(tài)的,原因:泛型參數(shù)是在調(diào)用方法時(shí)確定的,并非在實(shí)例化時(shí)確定。 public <E> List<E> copyFromArrayToList(E[] arr){ ArrayList<E> list = new ArrayList<>(); for(E e : arr){ list.add(e); } return list; } }
2.泛型在繼承方面的體現(xiàn)
1.泛型在繼承方面的體現(xiàn) 雖然類(lèi)A是類(lèi)B的父類(lèi),但是G<A>,和<B>二者不具備子父類(lèi)關(guān)系,二者是并列關(guān)系。 補(bǔ)充:類(lèi)A是類(lèi)B的父類(lèi),A<G>是B<G>的父類(lèi) public void test1(){ Object obj = null; String str = null; obj = str;//子類(lèi)對(duì)象賦值給父類(lèi);多態(tài)的體現(xiàn) Object[] arr1 = null; String[] arr2 = null; arr1 = arr2;//子類(lèi)對(duì)象賦值給父類(lèi);多態(tài)的體現(xiàn) //編譯不通過(guò) // Date date = new Date(); // str = date; List<Object> list1 = null; List<String> list2 = null; //此時(shí)的list1和list2的類(lèi)型不具有子父類(lèi)的關(guān)系 //編譯不通過(guò) // list1 = list2; } @Test public void test2(){ AbstractList<String> list1 = null; List<String> list2 = null; ArrayList<String> list3 = null; list1 = list3; list2 = list3; List<String> list4 = new ArrayList<>(); }
3.通配符的使用
@<?>
允許所有泛型的引用調(diào)用
@通配符指定上限
上限 extends :使用時(shí)指定的類(lèi)型必須是繼承某個(gè)類(lèi),或者實(shí)現(xiàn)某個(gè)接口,即<=
@通配符指定下限
下限 super :使用時(shí)指定的類(lèi)型不能小于操作的類(lèi),即>=
@舉例:
><? extends Number >(無(wú)窮小, Number ]
只允許泛型為 Number 及 Number 子類(lèi)的引用調(diào)用
><? super Number > INumber ,無(wú)窮大)
只允許泛型為 Number 及 Number 父類(lèi)的引用調(diào)用
><? extends Comparable >
只允許泛型為實(shí)現(xiàn) ComDarable 接口的實(shí)現(xiàn)類(lèi)的引用調(diào)用
/* 2.通配符的使用 通配符:? 類(lèi)A是類(lèi)B的父類(lèi),G<A>和G<B>是沒(méi)有關(guān)系的,二者共同的父類(lèi)是:G<?> */ @Test public void test3(){ List<Object> list1 = null; List<String> list2 = null; List<?> list = null; list = list1; list = list2; //編譯通過(guò) // print(list1); // print(list2); ArrayList<String> list3 = new ArrayList<>(); list3.add("AA"); list3.add("BB"); list3.add("CC"); list = list3; //添加(寫(xiě)入):對(duì)于List<?>就不能向其內(nèi)部添加數(shù)據(jù)。 //除了添加null之外。 // list.add("dd"); // list.add('d'); list.add(null); //獲取(讀取):允許讀取數(shù)據(jù),讀取的數(shù)據(jù)類(lèi)型為Object Object o = list.get(0); System.out.println(o); } public void print(List<?> list){ Iterator<?> iterator = list.iterator(); while(iterator.hasNext()){ Object obj = iterator.next(); System.out.println(obj); } } /* 3.有限制條件的通配符的使用。 ? extends A: G<? extends A> 可以作為G<A>和G<B>的父類(lèi),其中B是A的子類(lèi) ? super A: G<? super A> 可以作為G<A>和G<B>的父類(lèi),其中B是A的父類(lèi) */ @Test public void test4(){ List<? extends Person> list1 = null;//extends可理解為:小于等于 List<? super Person> list2 = null;//super可以理解為:大于等于 List<Student> list3 = new ArrayList<Student>(); List<Person> list4 = new ArrayList<Person>(); List<Object> list5 = new ArrayList<Object>(); list1 = list3; list1 = list4; // list1 = list5;//編譯報(bào)錯(cuò) // list2 = list3;//編譯報(bào)錯(cuò) list2 = list4; list2 = list5; //讀取數(shù)據(jù): list1 = list3; Person p = list1.get(0); //編譯不通過(guò): // Student s = list1.get(0); list2 = list4; Object obj = list2.get(0); //編譯不通過(guò) // Person obj = list2.get(0); //寫(xiě)入數(shù)據(jù): //編譯不通過(guò) // list1.add(new Student()); //編譯通過(guò) list2.add(new Person()); list2.add(new Student()); }
到此這篇關(guān)于深入淺出理解Java泛型的使用的文章就介紹到這了,更多相關(guān)Java泛型內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java中l(wèi)ambda表達(dá)式語(yǔ)法說(shuō)明
“Lambda 表達(dá)式”(lambda expression)是一個(gè)匿名函數(shù),Lambda表達(dá)式基于數(shù)學(xué)中的λ演算得名,直接對(duì)應(yīng)于其中的lambda抽象(lambda abstraction),是一個(gè)匿名函數(shù),即沒(méi)有函數(shù)名的函數(shù)。Lambda表達(dá)式可以表示閉包(注意和數(shù)學(xué)傳統(tǒng)意義上的不同)。2016-09-09mybatis3使用@Select等注解實(shí)現(xiàn)增刪改查操作
這篇文章主要介紹了mybatis3使用@Select等注解實(shí)現(xiàn)增刪改查操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-11-11springboot根據(jù)實(shí)體類(lèi)生成表的實(shí)現(xiàn)方法
本文介紹了如何通過(guò)SpringBoot工程引入SpringDataJPA,并通過(guò)實(shí)體類(lèi)自動(dòng)生成數(shù)據(jù)庫(kù)表的過(guò)程,包括常見(jiàn)問(wèn)題解決方法,感興趣的可以了解一下2024-09-09Springboot實(shí)現(xiàn)添加本地模塊依賴(lài)方式
這篇文章主要介紹了Springboot實(shí)現(xiàn)添加本地模塊依賴(lài)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-02-02Gateway網(wǎng)關(guān)自定義攔截器的不可重復(fù)讀取數(shù)據(jù)問(wèn)題
這篇文章主要介紹了Gateway網(wǎng)關(guān)自定義攔截器的不可重復(fù)讀取數(shù)據(jù)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08mybatis自動(dòng)生成時(shí)如何設(shè)置不生成Example類(lèi)詳解
這篇文章主要給大家介紹了關(guān)于mybatis自動(dòng)生成時(shí)如何設(shè)置不生成Example類(lèi)的相關(guān)資料,文中介紹的非常詳細(xì),對(duì)大家具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起看看吧。2017-05-05