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 @Override 100 public String toString() { 101 return "GenericeClass [t=" + t + "]"; 102 } 103 104 } 105 106 /** 107 * 测试泛型集合 108 */ 109 @Test 110 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 * @return 124 */ 125 private <E> Collection<E> createCollection(E t) { 126 // TODO Auto-generated method stub 127 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>) Arrays 133 .asList(new String[] { "测试集合1", "测试集合2", "测试集合3" }); 134 collection.addAll(initData); 135 } 136 return collection; 137 } 138 139 /** 140 * 创建Number集合 141 * 此方法不推荐使用 这里只是测试使用 142 * @return 143 */ 144 @Deprecated 145 private <E> Collection<E> createNumber() { 146 Collection<E> collection = new CopyOnWriteArrayList<E>(); 147 @SuppressWarnings("unchecked") 148 Collection<? extends E> initData = (Collection<? extends E>) Arrays 149 .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 src 159 */ 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-super 169 */ 170 @Test 171 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.out 180 .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.out 188 .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.out 196 .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.out 202 .println("之前一直有个疑惑,为什么Collection<Number>、Collection<Integer>、Collection<String>、Collection<Serializable>、Collection<List>调用的时候 能够返回相应的集合," 203 + "因为很明显 在createNumber方法中创建的是Number的List<Number>集合 我们有知道泛型是不可协变的 为什么会成功呢 "); 204 System.out 205 .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.List 212 */ 213 @Test 214 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 @Test 225 public void testOther() { 226 Integer integer = (int) 13.2; 227 String aString = String.valueOf(13.2); 228 } 229 230 }
时间: 2024-12-29 16:58:45