泛型
泛型:
jdk5以前,对象保存到集合中就会失去其特性,取出时通常要程序员时行类型的强制转换,这样,不可避免就会引发程序的一些安全性问题。
如:
ArrayList list = new ArrayList();
list.add("aaa");
Integer num = (Integer)list.get(0); //运行时会出错,但编码时发现不了
jdk5中的泛型允许程序员在编写集合代码时,就限制集合的处理类型,从而把原来程序运行时可能发生的问题,转变为编译时的问题,以提高程序的稳定性和可读性(尤其在大型程序中更为突出)。
在使用泛型时泛型类型必须为引用类型,不能是基本数据类型。
如果两边都使用了泛型,泛型的类型必须一致,但可以一边使用泛型,另一边不使用
注:泛型是提供给javac编译器使用的,它用于限制集合的输入类型,让编译器在源代码级别上,挡住向集合中插入非法数据。但编译器编译完带有泛型的java程序后,生成的class文件不再带有泛型信息,以此使程序运行效率不受影响,这个过程称之为“擦除”。
泛型的基本术语
- 以ArrayList<E>为例:<>读为“typeof”
- ArrayList<E>中的E称为类型参数变量
- ArrayList<Integer>中的Integer 称为实际类型参数
- 整个ArrayList<E>称为泛型类型
- 整个ArrayList<Integer>称为参数化的类型ParameterizedType
例1:基本泛型
1 import java.util.ArrayList; 2 import java.util.Iterator; 3 import java.util.LinkedHashMap; 4 import java.util.List; 5 import java.util.Map; 6 import java.util.Map.Entry; 7 import java.util.Set; 8 9 import org.junit.Test; 10 11 public class GenericTest { 12 13 @Test 14 public void test1(){ 15 //下面操纵的list中的类型只能为String 16 List<String> list = new ArrayList<String>(); 17 list.add("123"); 18 System.out.println(list.get(0)); 19 } 20 21 @Test 22 public void test2(){ 23 24 Map<Integer, String> map = new LinkedHashMap<Integer, String>(); 25 map.put(1, "A"); 26 map.put(2, "B"); 27 map.put(3, "C"); 28 map.put(4, "D"); 29 map.put(5, "E"); 30 31 Set<Entry<Integer,String>> entrySet = map.entrySet(); 32 for (Entry<Integer, String> entry : entrySet) { 33 Integer key = entry.getKey(); 34 String value = entry.getValue(); 35 System.out.println(key + ":" + value); 36 } 37 38 Set<Integer> keySet = map.keySet(); 39 Iterator<Integer> iterator = keySet.iterator(); 40 while(iterator.hasNext()){ 41 Integer key = iterator.next(); 42 System.out.println(key + ":" + map.get(key)); 43 } 44 } 45 }
例2:自定义泛型
1 public class GenericDemo { 2 3 4 public void testMethod1(){ 5 testMethod("张三"); 6 testMethod(123); 7 } 8 9 /** 10 * 自定义带泛型的方法,如下: -->自定义泛型,首先要先声明即<T> ,后边的(T t)为使用<T>这个泛型 11 * <T> 表示自定义的一个泛型,但未确切指定是什么类型, 12 * 在调用这个方法的时候,传入的参数是什么类型,则“T”表示的就是什么类型 13 * 如test1()中testMethod("张三")此时入参为String类型的,则“T”表示的类型就是String 14 * testMethod(123)为Integer类型,则“T”表示的类型就为Integer 15 */ 16 public <T> T testMethod(T t){ 17 return null; 18 } 19 20 /** 21 * 如下,多个泛型的方法 22 */ 23 public <T,E,K> void testMethod2(T t,E e,K k){ 24 25 } 26 } 27 28 /** 29 * 自定义类上的泛型 30 * 类上也可以声明泛型,作用范围就是整个类 31 */ 32 class TestDemo<T>{ 33 34 public T test(){ 35 return null; 36 } 37 public <E> void test1(T t,E e){ 38 39 } 40 41 /** 42 * 静态的方法,不能够使用类上定义的泛型,如果使用必须得在静态方法上自定义,且在static之后 43 */ 44 public static <T> void c(T t){ 45 46 } 47 }
例3:自定义泛型小例
1 import org.junit.Test; 2 3 public class GenericExample { 4 5 @Test 6 public void test1(){ 7 String[] arr = {"A","B","C","D","E","F"}; 8 genDemo(arr); 9 Integer[] arrInt = {1,2,3,4,5,6,7}; 10 genDemo(arrInt); 11 } 12 13 14 //用泛型写一个方法,将一数组中的元素反转过来 15 public <T> void genDemo(T arr[]){ 16 int len = arr.length - 1; 17 int start = 0; 18 while(true){ 19 if(start >= len){ 20 break; 21 } 22 T temp = arr[start]; 23 arr[start] = arr[len]; 24 arr[len] = temp; 25 start ++; 26 len --; 27 } 28 for (T t : arr) { 29 System.out.println(t); 30 //输出结果:FEDCBA7654321 31 } 32 } 33 }