标题: 关于泛型 [打印本页] 作者: fzy0723 时间: 2015-12-20 12:55 标题: 关于泛型 一、什么是泛型?List<String> list = new ArrayList<String>();这里的 <String> 就是常说的“泛型”,这一句代码表示:这个list只能用来存放 String,当你遍历这个list的时候,不用作任何检查,取出来的一定是 String 类型的对象。
二、为什么需要泛型?
要知道这个问题的答案,首先得知道“泛型究竟干了什么”。
List这个接口,其实先于泛型已经存在了,那时的代码是这样的:
List list = new ArrayList();
当你从这个list中取出一个元素的时候,一般需要用 instanceof 来检查它到底是不是你需要的类型,然后用强制类型转换来得到你要的类型的变量:
List list = getListMethod();
看这句变量声明的代码: Number n = Integer.valueOf(123);
编译器只知道变量n的类型是Number,而不知道“其具体类型是Integer”。这里Number就是变量n“声明”的类型。
而基于被声明的类型,编译器允许你进行合法的赋值: n = Double.valueOf(456.0);
编译器也知道这样的赋值不合法: n = "abc";
所以要编译器做类型检查,就得保证这个被检查的类型是声明的类型,换句话说,编译器只会检查声明的类型而不会检查具体(实际)的类型。
除了变量声明,还有两种类型声明是编译器所“知道”的:方法的参数类型,和方法的返回类型。
在泛型被使用之前,Java缺乏的就是在这几种声明中对类型做更详细更高级的描述的语法。
三、泛型的检查是怎样工作的?
例如:
List<String> list = new ArrayList<String>();
list.add("abc");
编译器知道list的类型是String,在所有使用list的代码被编译的时候,编译器会根据 List 接口中的方法中所写的参数类型或返回类型的声明,对其所操作的变量的声明类型做逐一检查。
编译之后,泛型的信息就被编译器“擦掉”了,所以和下面两句代码编译以后是没有什么区别的:
List<String> list = new ArrayList<String>();
List list = new ArrayList();
这两者的区别仅在于编译的过程。
这就保证了编译后代码的向前兼容。
四、泛型的特点,泛型 vs 数组
泛型与数组是有些合不来的,所以如果可能的话,尽量避免泛型与数组一起使用。比如下面的代码,是不合法的:
E[] arr = new E[10];