泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。
在Java SE 1.5之前,没有泛型的情况的下,通过对类型Object的引用来实现参数的“任意化”,“任意化”带来的缺点是要做显式的强制类型转换,而这种转换是要求开发者对实际参数类型可以预知的情况下进行的。对于强制类型转换错误的情况,编译器可能不提示错误,在运行的时候才出现异常,这是一个安全隐患。
3、泛型的基本用法
3.1 对于上面的问题我们只需要将上述代码的 List list = new ArrayList() 改为 List<String> list = new ArrayList<String>();
List list = new ArrayList (); //list.add(22); //向集合中添加一个 Integer 类型的数据时,编译器会报错 list.add("Bob"); //向集合中添加一个 String 类型的数据 list.add("Tom"); //向集合中添加一个 String 类型的数据 //如果我们遍历的时候就想得到自己想要的数据类型 for(int i = 0 ; i < list.size() ; i++){ String obj = list.get(i); //这里就不需要强转了,前面添加的是什么类型,这里获取的就是什么类型 System.out.println(obj); }
3.2 泛型是在编译阶段有效
List list1 = new ArrayList (); List list2 = new ArrayList(); Class c1 = list1.getClass(); Class c2 = list2.getClass(); System.out.println(c1==c2); //true
上述代码,由于我们知道反射是在运行时阶段,c1==c2为 true,说明了编译之后的 class 文件中是不包含任意的泛型信息的。如果不信,我们可以看 class 文件的反编译信息
java.util.List list1 = new ArrayList(); java.util.List list2 = new ArrayList(); Class c1 = list1.getClass(); Class c2 = list2.getClass(); System.out.println(c1.equals(c2));
public class Box { private T box; public T getBox(T t){ this.box = t; return t; } public void getType(){ System.out.println("T的实际类型为:"+box.getClass().getName()); } public static void main(String[] args) { Box box = new Box(); System.out.println(box.getBox(1)); box.getType(); System.out.println(box.getBox("Tom")); box.getType(); }}
public List wildCard(List list){ return list; } public static void main(String[] args) { GenericTest gt = new GenericTest(); //构造一个 Interger 类型的集合 List integer = new ArrayList (); integer.add(1); System.out.println(gt.wildCard(integer)); //构造一个 String 类型的集合 List str = new ArrayList (); gt.wildCard(str); //构造一个 Object 类型的集合 List