原做法:
Map m = new HashMap();
m.put("key", "blarg");
String s = (String) m.get("key");
泛型做法:
Map<K,V> m = new HashMap()<K,V>;
m.put("key", "blarg");//非<K,V>类型无法操作
String s = m.get("key");//获取无须强制转换
1:泛型(Generic type 或者 generics),对象类型的扩展,在对象类型相同情况下的一个参数化限定。
2:好处:提高程序的类型安全,将类型检查从运行时提前到编译时,入参限定检查阻止错误输入,出参无须强制类型转换。原类型可能对应的Object限定,实际运用需要更加细化。
3:它是编译阶段的类型检查,加泛型不影响JVM和类文件,反射操作可绕过泛型限定;
4:适用对象:除了异常类型、枚举或匿名内部类以外,任何类都可以具有类型参数
5:方式:声明对象时,使用<>加上大写单字母,
字母推荐: K —— 键,比如映射的键。
V —— 值,比如 List 和 Set 的内容,或者 Map 中的值。
E —— 异常类。
T —— 泛型。
6:注意:泛型不是 协定 的(协定的意思:假设A扩展自B,则使用B的地方可以使用A,即A是B的一种,非协变即泛型不支持继承,比较严格)
协定eg:
Integer[] intArray = new Integer[10];
Number[] numberArray = intArray;//valid
非协定eg1:
List<Integer> intList = new ArrayList<Integer>();
List<Number> numberList = intList; // invalid
numberList.add(new Float(3.1415));//编译出错,此处numberList是intList引用
非协定eg2:
void printList(List l) { //入参I可能因为参数类型限定为原始类型而出现类型不安全,假设入参为List<Integer>
for (Object o : l)
System.out.println(o);
}
非协定eg3:
void printList(List<Object> l) { //假设入参为List<Integer>,而List<Integer>不是List<Object>,参看非协变eg1.
for (Object o : l)
System.out.println(o);
}
由此引出 通配符 ? 通配符的引入在于可以安全检索元素(类型的任意限定肯定是扩展自Object),而非添加元素(编译器并不知道原类型的限定,添加是未知的,不被允许的)
非协定eg4:
void printList(List<?> l) { //List<?> 是任何泛型 List 的父类型,所以完全可以将 List<Object>、List<Integer> 或 List<List<List<Flutzpah>>> 传递给 printList()
for (Object o : l)
System.out.println(o);
}
7:泛型类(在类定义中添加一个形式类型参数列表),根据该定义可以在多个方法签名中实施类型约束
8:方法的泛型化与所在的类是否为泛型类无关,泛型方法用于在该方法的多个参数之间宣称一个类型约束
eg:
public <T> T ifThenElse(boolean b, T first, T second) {//不用显式地告诉编译器T是什么,它只需要做到带T的参数及返回值都是同一类型即可
return b ? first : second;
}
9:泛型类和泛型方法的选择
a:当泛型方法是静态方法时,编译器无法知道该类到底是什么泛型,故不用泛型类而用泛型方法
b:当T约束仅针对方法,局部约束的时候不需要泛型类,因为泛型类的约束会导致所有的实例对象都是用的同一个T,导致该方法也是使用的同一个T,而存在这种需求:A类的实例a1和a2的方法的类型约束不需要一样;
10:限定类型,附加约束(类-----无泛型,类类型-------一般泛型,类类型约束------带约束泛型)
eg:
public class Matrix<V extends Number> { ... }//Matrix由哪个泛型限定不知道,但必须是Number或Number子类;若无泛型,假设由Object限定,这样可以解释List.get() 在 List<?> 上调用时返回 Object
public static void main(String[] args) {
Matrix<Number> in = new Matrix<Number>();//valid
Matrix<Integer> in = new Matrix<Integer>();//valid
Matrix<Float> in = new Matrix<Float>();//valid
}
整理自:http://www.cnblogs.com/panjun-Donet/archive/2008/09/27/1300609.html