泛型
java中的泛型是针对编译器的,在编译之后,我们定义的不同的泛型就会变成一样的类型,即所谓的“泛型檫除”。
比如List<String>和List<Integer>,它们都是泛型,经过编译之后都是变成List。这里的类型檫除是说泛型的檫除,而不是其中的元素不知其类型了。
第一个集合当中的元素本质仍然是String类型,第二个集合当中的元素本质上仍是Integer类型。
泛型的作用,仅仅只是在编程层面上起一种约束作用。也就是如果泛型的参数是如果是String类型的,那么我们只能往里面添加String类型的元素,但是经过
编译后,因为存在“泛型檫除”,所以这种约束性将不复存在。如果我们能在运行时期拿到这个泛型类,就能往里面添加任意类型。比如我们通过反射技术拿到。
1 public class GenericTypes { 2 public static void method(List<String> list) { 3 System.out.println("invoke method (List<String>list)"); 4 } 5 6 public static void method(List<Integer> list) { 7 System.out.println("invoke method (List<Integer>list)"); 8 } 9 }
上面程序的目的就是想重载method方法,但是编译不能通过,因为如果它能通过编译,那么它就等价于下面的代码:
1 public class GenericTypes { 2 public static void method(List list) { 3 System.out.println("invoke method (List<String>list)"); 4 } 5 6 public static void method(List list) { 7 System.out.println("invoke method (List<Integer>list)"); 8 } 9 }
这两个方法的方法名、方法参数完全相同当然不能进行重载。这也验证了“泛型檫除”。
1 public static void main(String[]args) { 2 List<Integer> list=new ArrayList<Integer> (); 3 list.add(1); 4 list.add(2); 5 List list1=list; //相当于编译期间做了的事 6 for(int i=0;i<list1.size();i++) { 7 String str=(String)list1.get(i); //相当于运行期间做了的事 8 } 9 }
假设我们定义了一个List<Integer>的泛型。在编译阶段就会对泛型类型进行檫除,相当于第5行代码做的事。这样我们添加到其中的元素都会以Object
类型进行接收,但是本质上都是相应的泛型约束里的类型,这里为Integer。因此,当我们将其强制转换成String类型时,就会抛出ClassCastException。
1 public static void main(String[]args) { 2 List<Integer> list=new ArrayList<Integer> (); 3 List list1=list; //相当于编译期间做了的事 4 list1.add("fei"); ////相当于运行期间做了的事 5 list1.add("ji"); 6 list1.add("shuo"); 7 for(int i=0;i<list1.size();i++) { 8 String str=(String)list1.get(i); 9 System.out.print(str); 10 } 11 }
这段代码即表示,如果我们在编译之后,即进行了泛型檫除之后,就可以往泛型类中加入任何类型的元素。即丧失了即原先的泛型约束。