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