什么是泛型(Generic Type)?
泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。
Java 在 J2SE 1.5 版本添加了对泛型的支持。为什么需要泛型呢?在JAVA中,总是不可避免的需要 downcast ,但是每个 downcast 对于ClassCastException
而言都是潜在的危险,应当尽量避免它们。而 J2SE 1.5之前即便再优良的设计也不可避免。例如:
class Hashtable { Object put(Object key, Object value) {...} Object get(Object key) {...} ...}class Test { public static void main(String[] args) { Hashtable h = new Hashtable(); h.put(new Integer(0), "value"); String s = (String)h.get(new Integer(0)); System.out.println(s); }}
如果使用泛型,我们可以这么解决问题:
class Hashtable<Key, Value> {
...
Value put(Key k, Value v) {...}
Value get(Key k) {...}
}
class Test {
public static void main(String[] args) {
Hashtable<Integer, String> h = new Hashtable<Integer, String>();
h.put(new Integer(0), "value");
...
}
}
略过泛型的具体使用介绍,我们来看看几件必须知道的事情:
1. 必须用引用类型进行实例化,基本类型不起作用。
因此,在上面示例中,无法完成创建从 int 映射到 String 的 Hashtable 。
2.泛型不支持类继承
List<Number> numbers = new ArrayList<Integer>(); // will not compile
List<Long> list = new ArrayList<Long>();
List<Number> numbers = list; // this will not compile
3.在JAVA中,泛型的实现是擦除法。
编译器在生成类文件时基本上会抛开参数化类的大量类型信息。也就是说编译器会将泛型类型以其父类代替,如String变成了Object等。
尽管不能将 List<Integer> 赋给 List<Number>,但是
new List<Number>().getClass() == new List<Integer>().getClass()
4.不能创建泛型数组
T[] arr = new T[10];// this code will not compile
List<Integer>[] array = new List<Integer>[10]; // does not compile
因为数组本身是支持类继承的:
Number[] a = new Number[10];
a[1] = Integer.valueOf(1);
4.不能创建泛型数组
T[] arr = new T[10];// this code will not compile
List<Integer>[] array = new List<Integer>[10]; // does not compile
因为数组本身是支持类继承的。
Number[] a = new Number[10]; a[1] = Integer.valueOf(1);
5.使用通配符
5.1 <? extends E>
java.util.List.java
boolean addAll(Collection<? extends E> c);
List<? extends Long> list = new ArrayList();
List<Long> longlist = new ArrayList();
list = longlist;
5.2 <? super E>
List<? super Long> list = new ArrayList();
List<Number> longlist = new ArrayList();
list = longlist;
6. Multiple Bounds
例如你定义约束是这个类必须是Number,并且应该继承i
public static <T extends Number & Comparable<? super T>> int compareNumbers(T t1, T t2){
return t1.compareTo(t2);
}
public static <T extends String & Number > int compareNumbers(T t1, T t2) // does not work..can't have two classes
public static <T extends Comparable<? super T> & Number > int compareNumbers(T t1, T t2) // does not work..
public static <T extends CharSequence & Comparable<T>> int compareNumbers(T t1, T t2)// works..multiple interfaces