泛型:就是允许在定义类,接口,方法时使用类型形参,这个类型形参将在声明变量、创建对象、调用方法时动态的指定(即传入实际的类型参数,称为类型实参)。
JDK1.5增加了对泛型的支持,Java泛型可以保证如果在编译期间没有发出警告时,运行时也不会产生ClassCastException异常,在使用泛型时,如果没有指明参数类型,即没有指定实际的类型参数,则会发出警告,且此时的类型默认为Objec。
为什么要使用泛型?
以Java集合为例:为了保证Java集合的通用性,集合被设计成可以保存任何类型的对象,这样会产生两个问题:
---->由于集合对元素的类型没有任何限制,那么在一个集合中保存不同类型的元素时,可能会引发异常;
---->由于集合丢失了对象的状态信息,所有元素都默认为Object类型,取出元素时还要强制类型转换,转换到特定的类型,不但增加了代码的复杂度,还可能会引起运行时异常。
举例说明:
1 import java.util.ArrayList; 2 import java.util.List; 3 4 public class Testerr { 5 6 public static void main(String[] args) { 7 8 //创建一个只想保存字符串的List 9 List strList= new ArrayList(); 10 strList.add("aaaa"); 11 strList.add("bbbb"); 12 //“不小心”存了一个Integer对象的元素 13 strList.add(5); //1 14 15 for (int i = 0; i < strList.size(); i++) { 16 17 //集合中所有的元素都是Object类型,所以需要强制类型转换 18 String string = (String) strList.get(i); //2 19 System.out.println(string); 21 } 23 } 25 }
程序创建了一个只想保存String类型的List,但由于集合对元素类型没有任何限制,//1处往集合存入一个Integer对象的元素,编译没有错误,但会导致程序在//2处引发ClassCastException异常,因为程序试图把一个Integer对象转换为String类型。
使用泛型后:
1 import java.util.ArrayList; 2 import java.util.List; 3 4 public class Testerr { 5 6 public static void main(String[] args) { 23 //创建一个只想保存字符串的List 24 List<String> strList= new ArrayList<String>(); //1 25 strList.add("aaaa"); 26 strList.add("bbbb"); 27 //编译错误 28 strList.add(5); //2 30 for (int i = 0; i < strList.size(); i++) { 32 //不需要强制类型转换 33 String string = strList.get(i); //3 34 System.out.println(string); 36 } 38 } 39 40 }
//1处程序创建了一个只能保存String类型的特殊的集合,List<String>称之为带有一个类型参数的泛型接口,在本程序中,类型参数是String;
//2处引发编译异常,因为stList只能添加String对象,故不能在集合里添加Integer对象的元素;
//3处不需要强制类型转换,strList对象里所有的集合元素都是String类型的。
使用泛型后,代码更加简洁,程序也不能往集合对象中添加与类型参数不一致的元素,程序更加简洁,集合会自动记住所有集合元素的数据类型,从而无须对集合元素进行强制类型转换,这些都是使用了泛型的优点。