Java_generics
Contents
什么是泛型
先看Java标准库中的ArrayList ,这是一个“可变长”数组。内部通过Object[]数组实现
public class ArrayList {
private Object[] array;
private int size;
public void add(Object e) {...}
public void remove(int index) {...}
public Object get(int index) {...}
}
在很久很久以前(泛型之前)如果用ArrayList存储String类型,需要强制转型
ArrayList list = new ArrayList();
list.add("Hello");
// 获取到Object,必须强制转型为String:
String first = (String) list.get(0);
后来出现了泛型,可以把ArrayList变成一种模板ArrayList<T> 编写一次模版,可以创建任意类型的ArrayList:
public class ArrayList<T> {
private T[] array;
private int size;
public void add(T e) {...}
public void remove(int index) {...}
public T get(int index) {...}
}
// 创建可以存储String的ArrayList:
ArrayList<String> strList = new ArrayList<String>();
// 创建可以存储Float的ArrayList:
ArrayList<Float> floatList = new ArrayList<Float>();
// 创建可以存储Person的ArrayList:
ArrayList<Person> personList = new ArrayList<Person>();
向上转型
在Java标准库中的ArrayList<T>实现了List<T>接口,它可以向上转型为List<T> 。同时通过List<String>定义后 编译器可以自动推断出是String类型。因此可以简写
List<String> list = new ArrayList<String>();
// 简写
List<String> list = new ArrayList<>();
编写泛型
通常来说,泛型类一般用在集合类中。示例如下:可以看到和普通类的区别在于,定义是多了一个<T>,变量类型也都是<T>
public class Pair<T> {
private T first;
private T last;
public Pair(T first, T last) {
this.first = first;
this.last = last;
}
public T getFirst() {
return first;
}
public T getLast() {
return last;
}
}
静态方法
编写泛型类时,要特别注意,泛型类型<T>不能用于静态方法。原因是这个参数对于类的所有实例方法和成员变量可见,但是静态方法属于类本身,而不属于类的任何实例。静态方法在类加载时就已经存在,早于任何类的实例的创建。所以静态方法不能直接访问类级别的泛型类型参数 <T> 正确做法是——在静态方法上单独声明泛型类型参数<K>。
public class Pair<T> {
private T first;
private T last;
public Pair(T first, T last) {
this.first = first;
this.last = last;
}
public T getFirst() { ... }
public T getLast() { ... }
// 静态泛型方法应该使用其他类型区分:
public static <K> Pair<K> create(K first, K last) {
return new Pair<K>(first, last);
}
}