1 * 泛型-->类或者接口的声明中拥有一个或多个类型参数时,称为泛型类/泛型接口,简称泛型 2 * 泛型在安全性和表述性上都比原生态类型更具有优势 3 * 泛型是不可变的,无法向数组一样形成协变关系 4 * (Sub extends Super,同时可支持Sub[] extends Super[]) 5 * (Sub extends Super,不支持List<Sub> extends List<Super>) 6 * 泛型在编译时检查其元素类型信息,而在运行期舍弃其元素类型信息 7 * 每个类都是自身的子类型和超类型 8 * T 形式类型参数 9 * E 集合中的形式类型参数 10 * K Map中的键形式参数 11 * V Map中的值形式参数 12 * ? 任意匹配的配型参数 <? extends E>/<? super E>13 * 有限的通配符形式参数(PECS)14 * 15 * Class<T> 泛型 16 * Class<String> 参数化的类型 17 * Class 原生态类型(删除了所有的泛型信息) 18 * Class<?> 无限制的通配符类型19 * Class<? extends E> 有限制的通配符类型20 * <T> 形式类型参数 21 * <String> 实际类型参数22 * 23 * static <E> E get(E e) 泛型方法24 * (<E> 称为类型参数列表,即在调用方法之前告诉编译器,此方法中的类型都是什么类型)25 * 编译器使用泛型方法可通过类型推导,推导出类型参数列表的类型
测试代码
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 * 泛型学习测试代码 14 * 15 * 泛型-->类或者接口的声明中拥有一个或多个类型参数时,称为泛型类/泛型接口,简称泛型 16 * 泛型在安全性和表述性上都比原生态类型更具有优势 17 * 泛型是不可变的,无法向数组一样形成协变关系 18 * (Sub extends Super,同时可支持Sub[] extends Super[]) 19 * (Sub extends Super,不支持List<Sub> extends List<Super>) 20 * 泛型在编译时检查其元素类型信息,而在运行期舍弃其元素类型信息 21 * 每个类都是自身的子类型和超类型 22 * T 形式类型参数 23 * E 集合中的形式类型参数 24 * K Map中的键形式参数 25 * V Map中的值形式参数 26 * ? 任意匹配的配型参数 <? extends E>/<? super E> 27 * 有限的通配符形式参数(PECS) 28 * 29 * Class<T> 泛型 30 * Class<String> 参数化的类型 31 * Class 原生态类型(删除了所有的泛型信息) 32 * Class<?> 无限制的通配符类型 33 * Class<? extends E> 有限制的通配符类型 34 * <T> 形式类型参数 35 * <String> 实际类型参数 36 * 37 * static <E> E get(E e) 泛型方法 38 * (<E> 称为类型参数列表,即在调用方法之前告诉编译器,此方法中的类型都是什么类型) 39 * 编译器使用泛型方法可通过类型推导,推导出类型参数列表的类型 40 * 41 * 此内容主要涉及泛型类和泛型方法,测试用例-->testGenericeClass 42 * 泛型集合-->testGeneCollection 43 * 有限的通配符使用-->testBoundWildType 44 * 泛型编译器维护类型信息,运行时舍弃-->testEraseGenericsInfo 45 * 46 * @author Administrator 47 * 48 */ 49 public class GenericsLearn { 50 51 /** 52 * 测试泛型类和方法 53 */ 54 @Test 55 public void testGenericeClass() { 56 GenericeClass<String> gClass1 = new GenericeClass<String>("测试泛型类参数"); 57 System.out.println(gClass1); 58 System.out.println(gClass1.getAddSome("泛型方法")); 59 System.out.println(gClass1.getAddSome(123)); 60 } 61 62 /** 63 * 泛型测试类 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 * 获取对象后 添加附加信息 79 * 80 * @param t 81 * @return 82 */ 83 public <E> E getAddSome(E t) { 84 if (t instanceof String) { 85 // 因为在进入此方法时 已做了类型判断 使用注解消除非受检警告 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 * 测试泛型集合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 * 创建测试集合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 // 已经进行类类型检查 所以转换时没有问题的 每个类都是自身的子类型和超类型131 @SuppressWarnings("unchecked")132 Collection<? extends E> initData = (Collection<? extends E>) Arrays133 .asList(new String[] { "测试集合1", "测试集合2", "测试集合3" });134 collection.addAll(initData);135 }136 return collection;137 }138 139 /**140 * 创建Number集合141 * 此方法不推荐使用 这里只是测试使用 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 * 迭代实现了Iterable接口的可迭代子类157 * 158 * @param src159 */160 public <E> void iterator(Iterable<E> src) {161 for (E e : src) { // 内部通过迭代器来遍历元素162 System.out.println(e);163 }164 }165 166 /**167 * 测试有限的通配符类型 每个类都是自身的子类型和超类型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 // 创建Number数组176 Collection<Number> collection = createNumber();177 iterator(collection);178 // 使用GenericeClass的迭代方法进行迭代 每个类都是自身的子类型和超类型179 System.out180 .println("使用有限的通配符进行迭代 形式为:Iterable<? extends T> 实际为:Iterable<Number extends Number> 每个类都是自身的子类型和超类型");181 gClass1.iterator(collection);182 Collection<Integer> collection2 = createNumber();183 // 使用foreach进行迭代184 System.out.println("使用foreach进行迭代");185 iterator(collection2);186 // 使用有限的通配符进行迭代187 System.out188 .println("使用有限的通配符进行迭代 形式为:Iterable<? extends T> 实际为:Iterable<Integer extends Number>");189 gClass1.iterator(collection2);190 System.out.println("进行字符串集合的foreach迭代");191 Collection<String> collection3 = createNumber();192 iterator(collection3);193 System.out.println("如果使用collection3.add(123)方法,泛型的安全性检查就会得到体现,编译器会报错");194 // collection3.add(123);195 System.out196 .println("如果调用gClass1.iterator(collection3)方法,就会有问题,因为形式为:Iterable<? extends T> 实际为: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("之前一直有个疑惑,为什么Collection<Number>、Collection<Integer>、Collection<String>、Collection<Serializable>、Collection<List>调用的时候 能够返回相应的集合,"203 + "因为很明显 在createNumber方法中创建的是Number的List<Number>集合 我们有知道泛型是不可协变的 为什么会成功呢 ");204 System.out205 .println("因为泛型在编译器检查其类型信息(所以当定义Collection<Serializable> collection4 = createNumber();的时候 调用createNumber,而此方法只会进行类型检查,createNumber为泛型方法,所以编译时是没有问题的),而在运行时丢弃其元素类型信息,并且强制类型转换是在运行期进行的,所以在(Collection<? extends E>)强制类型转换实际上是(Collection)List,所以运行期也没有问题,调试一下就知道了,害我想了1个多小时");206 }207 208 /**209 * 测试泛型只在编译器维护其类型信息 在运行期不会维护其元素的类型信息 210 * 下面代码会报错 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 }