泛型的概念
最简单的理解泛型的方式是,想一想类型转换的问题:
List<Apple> box = ...;
Apple apple = box.get(0);
这段代码是自解释的:box是一个对list对象的引用;list中的对象是apple。从list中取出对象时,不再需要类型转换。如果没有泛型,那么这段代码应该是:
List box = ...;
Apple apple = (Apple) box.get(0);
从上例可以看出,泛型的主要优点是,编译器可以跟踪,检查对象的类型:编译器可以保证永远不会出现类型转换失败的问题(很可能在运行时出现);
与其让程序员来保证类型不会弄错,并在运行时进行类型转换,使用泛型可以让编译器来强制进行类型检查,并且在编译时就能发现错误。
因此,当我们使用泛型(其实就是在代码中加入了类型变量)时,就等于告诉编译器:请帮我做类型检查,并在必要的时候自动进行类型转换。
在代码中使用泛型
1,泛型类:
当一个类或接口有一个或多个类型变量时,它就是泛型。类型变量在<>内,并且紧跟在类名或接口名后面:
public interface List<T> extends Collection<T> {
...
}
在java中,很多类已经被修改称为泛型类了。例如整个collections。我们在第一段代码中使用的List接口,就是一个泛型类。
2,泛型方法和构造函数
类似的,方法和构造函数也可以是泛型的,如果他们也使用了类型变量。
public static <t> Apple getFirst(List<Apple> list){
Apple apple = new Apple();
return apple;
}
泛型的应用
1,类型安全 前面已经提到了。
2,迭代器 在使用迭代器时做类型检查太合理了。
for (Iterator<String> iter = str.iterator(); iter.hasNext();) {
String s = iter.next();
System.out.print(s);
}
3,for each
4, 自动装箱和拆箱
List<Integer> ints = new ArrayList<Integer>();
ints.add(0);
ints.add(1);
int sum = 0;
for (int i : ints) {
sum += i;
}
聪明的同学可能已经发现了,上例中List中声明的类型是Integer而不是int:
List<int> ints = new ArrayList<int>();
如果这么写会报错: Syntax error on token "int", Dimensions expected after this token
这是因为java的collection只能存储对象引用(Collections can onlyhold object references),而int不是对象,而是primitives。
因此对应的,在泛型中,也不可以使用primitives了。
参考下面这个帖子:
http://stackoverflow.com/questions/2001755/using-int-as-a-type-parameter-for-java-util-dictionary
所以我们得知道java中常见的primitives以及对应的object。其实在java中,就像类的名字总是首字母大写的规律一样,如果类型的名字是小写的,那么就是primitives:
int -- Integer
char -- Character
boolean -- Boolean
而String就不是primitive的,S是大写的。