1 * 泛型-->類或者接口的聲明中擁有一個(gè)或多個(gè)類型參數(shù)時(shí),稱為泛型類/泛型接口,簡(jiǎn)稱泛型 2 * 泛型在安全性和表述性上都比原生態(tài)類型更具有優(yōu)勢(shì) 3 * 泛型是不可變的,無(wú)法向數(shù)組一樣形成協(xié)變關(guān)系 4 * (Sub extends Super,同時(shí)可支持Sub[] extends Super[]) 5 * (Sub extends Super,不支持List<Sub> extends List<Super>) 6 * 泛型在編譯時(shí)檢查其元素類型信息,而在運(yùn)行期舍棄其元素類型信息 7 * 每個(gè)類都是自身的子類型和超類型 8 * T 形式類型參數(shù) 9 * E 集合中的形式類型參數(shù) 10 * K Map中的鍵形式參數(shù) 11 * V Map中的值形式參數(shù) 12 * ? 任意匹配的配型參數(shù) <? extends E>/<? super E>13 * 有限的通配符形式參數(shù)(PECS)14 * 15 * Class<T> 泛型 16 * Class<String> 參數(shù)化的類型 17 * Class 原生態(tài)類型(刪除了所有的泛型信息) 18 * Class<?> 無(wú)限制的通配符類型19 * Class<? extends E> 有限制的通配符類型20 * <T> 形式類型參數(shù) 21 * <String> 實(shí)際類型參數(shù)22 * 23 * static <E> E get(E e) 泛型方法24 * (<E> 稱為類型參數(shù)列表,即在調(diào)用方法之前告訴編譯器,此方法中的類型都是什么類型)25 * 編譯器使用泛型方法可通過(guò)類型推導(dǎo),推導(dǎo)出類型參數(shù)列表的類型
測(cè)試代碼
1 package com.undergrowth.lang; 2 3 import java.io.Serializable; 4 import java.util.Arrays; 5 import java.util.Collection; 6 import java.util.Collections; 7 import java.util.List; 8 import java.util.concurrent.CopyOnWriteArrayList; 9 10 import org.junit.Test; 11 12 /** 13 * 泛型學(xué)習(xí)測(cè)試代碼 14 * 15 * 泛型-->類或者接口的聲明中擁有一個(gè)或多個(gè)類型參數(shù)時(shí),稱為泛型類/泛型接口,簡(jiǎn)稱泛型 16 * 泛型在安全性和表述性上都比原生態(tài)類型更具有優(yōu)勢(shì) 17 * 泛型是不可變的,無(wú)法向數(shù)組一樣形成協(xié)變關(guān)系 18 * (Sub extends Super,同時(shí)可支持Sub[] extends Super[]) 19 * (Sub extends Super,不支持List<Sub> extends List<Super>) 20 * 泛型在編譯時(shí)檢查其元素類型信息,而在運(yùn)行期舍棄其元素類型信息 21 * 每個(gè)類都是自身的子類型和超類型 22 * T 形式類型參數(shù) 23 * E 集合中的形式類型參數(shù) 24 * K Map中的鍵形式參數(shù) 25 * V Map中的值形式參數(shù) 26 * ? 任意匹配的配型參數(shù) <? extends E>/<? super E> 27 * 有限的通配符形式參數(shù)(PECS) 28 * 29 * Class<T> 泛型 30 * Class<String> 參數(shù)化的類型 31 * Class 原生態(tài)類型(刪除了所有的泛型信息) 32 * Class<?> 無(wú)限制的通配符類型 33 * Class<? extends E> 有限制的通配符類型 34 * <T> 形式類型參數(shù) 35 * <String> 實(shí)際類型參數(shù) 36 * 37 * static <E> E get(E e) 泛型方法 38 * (<E> 稱為類型參數(shù)列表,即在調(diào)用方法之前告訴編譯器,此方法中的類型都是什么類型) 39 * 編譯器使用泛型方法可通過(guò)類型推導(dǎo),推導(dǎo)出類型參數(shù)列表的類型 40 * 41 * 此內(nèi)容主要涉及泛型類和泛型方法,測(cè)試用例-->testGenericeClass 42 * 泛型集合-->testGeneCollection 43 * 有限的通配符使用-->testBoundWildType 44 * 泛型編譯器維護(hù)類型信息,運(yùn)行時(shí)舍棄-->testEraseGenericsInfo 45 * 46 * @author Administrator 47 * 48 */ 49 public class GenericsLearn { 50 51 /** 52 * 測(cè)試泛型類和方法 53 */ 54 @Test 55 public void testGenericeClass() { 56 GenericeClass<String> gClass1 = new GenericeClass<String>("測(cè)試泛型類參數(shù)"); 57 System.out.PRintln(gClass1); 58 System.out.println(gClass1.getAddSome("泛型方法")); 59 System.out.println(gClass1.getAddSome(123)); 60 } 61 62 /** 63 * 泛型測(cè)試類 64 * 65 * @author Administrator 66 * 67 * @param <T> 68 */ 69 private static class GenericeClass<T> { 70 private final T t; 71 72 public GenericeClass(T t) { 73 super(); 74 this.t = t; 75 } 76 77 /** 78 * 獲取對(duì)象后 添加附加信息 79 * 80 * @param t 81 * @return 82 */ 83 public <E> E getAddSome(E t) { 84 if (t instanceof String) { 85 // 因?yàn)樵谶M(jìn)入此方法時(shí) 已做了類型判斷 使用注解消除非受檢警告 86 @SuppressWarnings("unchecked") 87 E t1 = (E) (String.valueOf(t) + ",附加泛型防范新消息"); 88 return t1; 89 } 90 return t; 91 } 92 93 public void iterator(Iterable<? extends T> src) { 94 for (T t : src) { 95 System.out.println(t); 96 } 97 } 98 99 @Override100 public String toString() {101 return "GenericeClass [t=" + t + "]";102 }103 104 }105 106 /**107 * 測(cè)試泛型集合108 */109 @Test110 public void testGeneCollection() {111 Collection<String> collection = createCollection("123");112 /*113 * for (Iterator<String> iterator = collection.iterator();114 * iterator.hasNext();) { String string = (String) iterator.next();115 * System.out.println(string); }116 */117 iterator(collection);118 }119 120 /**121 * 創(chuàng)建測(cè)試集合122 * 123 * @return124 */125 private <E> Collection<E> createCollection(E t) {126 // TODO Auto-generated method stub127 Collection<E> collection = Collections.emptyList();128 if (t instanceof String) {129 collection = new CopyOnWriteArrayList<E>();130 // 已經(jīng)進(jìn)行類類型檢查 所以轉(zhuǎn)換時(shí)沒(méi)有問(wèn)題的 每個(gè)類都是自身的子類型和超類型131 @SuppressWarnings("unchecked")132 Collection<? extends E> initData = (Collection<? extends E>) Arrays133 .asList(new String[] { "測(cè)試集合1", "測(cè)試集合2", "測(cè)試集合3" });134 collection.addAll(initData);135 }136 return collection;137 }138 139 /**140 * 創(chuàng)建Number集合141 * 此方法不推薦使用 這里只是測(cè)試使用 142 * @return143 */144 @Deprecated145 private <E> Collection<E> createNumber() {146 Collection<E> collection = new CopyOnWriteArrayList<E>();147 @SuppressWarnings("unchecked")148 Collection<? extends E> initData = (Collection<? extends E>) Arrays149 .asList(new Number[] { 123.2, Integer.MAX_VALUE, 789 });150 // System.out.println(initData.getClass().getName());151 collection.addAll(initData);152 return collection;153 }154 155 /**156 * 迭代實(shí)現(xiàn)了Iterable接口的可迭代子類157 * 158 * @param src159 */160 public <E> void iterator(Iterable<E> src) {161 for (E e : src) { // 內(nèi)部通過(guò)迭代器來(lái)遍歷元素162 System.out.println(e);163 }164 }165 166 /**167 * 測(cè)試有限的通配符類型 每個(gè)類都是自身的子類型和超類型168 * PECS原則-->producer-extends,consumer-super169 */170 @Test171 public void testBoundWildType() {172 GenericeClass<Number> gClass1 = new GenericeClass<Number>(123456);173 System.out.println(gClass1);174 System.out.println(gClass1.getAddSome("123456"));175 // 創(chuàng)建Number數(shù)組176 Collection<Number> collection = createNumber();177 iterator(collection);178 // 使用GenericeClass的迭代方法進(jìn)行迭代 每個(gè)類都是自身的子類型和超類型179 System.out180 .println("使用有限的通配符進(jìn)行迭代 形式為:Iterable<? extends T> 實(shí)際為:Iterable<Number extends Number> 每個(gè)類都是自身的子類型和超類型");181 gClass1.iterator(collection);182 Collection<Integer> collection2 = createNumber();183 // 使用foreach進(jìn)行迭代184 System.out.println("使用foreach進(jìn)行迭代");185 iterator(collection2);186 // 使用有限的通配符進(jìn)行迭代187 System.out188 .println("使用有限的通配符進(jìn)行迭代 形式為:Iterable<? extends T> 實(shí)際為:Iterable<Integer extends Number>");189 gClass1.iterator(collection2);190 System.out.println("進(jìn)行字符串集合的foreach迭代");191 Collection<String> collection3 = createNumber();192 iterator(collection3);193 System.out.println("如果使用collection3.add(123)方法,泛型的安全性檢查就會(huì)得到體現(xiàn),編譯器會(huì)報(bào)錯(cuò)");194 // collection3.add(123);195 System.out196 .println("如果調(diào)用gClass1.iterator(collection3)方法,就會(huì)有問(wèn)題,因?yàn)樾问綖椋篒terable<? extends T> 實(shí)際為:Iterable<String extends Number>");197 // gClass1.iterator(collection3);198 System.out.println("獲取Serializable集合");199 Collection<Serializable> collection4 = createNumber();200 iterator(collection4);201 System.out202 .println("之前一直有個(gè)疑惑,為什么Collection<Number>、Collection<Integer>、Collection<String>、Collection<Serializable>、Collection<List>調(diào)用的時(shí)候 能夠返回相應(yīng)的集合,"203 + "因?yàn)楹苊黠@ 在createNumber方法中創(chuàng)建的是Number的List<Number>集合 我們有知道泛型是不可協(xié)變的 為什么會(huì)成功呢 ");204 System.out205 .println("因?yàn)榉盒驮诰幾g器檢查其類型信息(所以當(dāng)定義Collection<Serializable> collection4 = createNumber();的時(shí)候 調(diào)用createNumber,而此方法只會(huì)進(jìn)行類型檢查,createNumber為泛型方法,所以編譯時(shí)是沒(méi)有問(wèn)題的),而在運(yùn)行時(shí)丟棄其元素類型信息,并且強(qiáng)制類型轉(zhuǎn)換是在運(yùn)行期進(jìn)行的,所以在(Collection<? extends E>)強(qiáng)制類型轉(zhuǎn)換實(shí)際上是(Collection)List,所以運(yùn)行期也沒(méi)有問(wèn)題,調(diào)試一下就知道了,害我想了1個(gè)多小時(shí)");206 }207 208 /**209 * 測(cè)試泛型只在編譯器維護(hù)其類型信息 在運(yùn)行期不會(huì)維護(hù)其元素的類型信息 210 * 下面代碼會(huì)報(bào)錯(cuò) java.lang.ClassCastException:211 * java.lang.Double cannot be cast to java.util.List212 */213 @Test214 public void testEraseGenericsInfo() {215 System.out.println("獲取List集合");216 Collection<List> collection5 = createNumber();217 for (List list : collection5) {218 System.out.println(list.get(0));219 ;220 }221 }222 223 224 @Test225 public void testOther() {226 Integer integer = (int) 13.2;227 String aString = String.valueOf(13.2);228 }229 230 }新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注