命名类型参数 推荐的命名约定是使用大写的单个字母名称作为类型参数。这与 C++ 约定有所不同(参阅 附录 A:与 C++ 模板的比较),并反映了大多数泛型类将具有少量类型参数的假定。对于常见的泛型模式,推荐的名称是: K —— 键,比如映射的键。 V —— 值,比如 List 和 Set 的内容,或者 Map 中的值。 E —— 异常类。 T —— 泛型。
类型通配符 假设您具有该方法:
1 | void printList(List l) { |
---|
2 | for (Object o : l) |
---|
3 | System.out.println(o); |
---|
4 | } |
---|
上面的代码在 JDK 5.0 上编译通过,但是如果试图用 List<Integer> 调用它,则会得到警告。出现警告是因为,您将泛型(List<Integer>)传递给一个只承诺将它当作 List(所谓的原始类型)的方法,这将破坏使用泛型的类型安全。 如果试图编写像下面这样的方法,那么将会怎么样?
1 | void printList(List<Object> l) { |
---|
2 | for (Object o : l) |
---|
3 | System.out.println(o); |
---|
4 | } |
---|
它仍然不会通过编译,因为一个 List<Integer> 不是 一个 List<Object>(正如前一屏 泛型不是协变的 中所学的)。这才真正烦人 —— 现在您的泛型版本还没有普通的非泛型版本有用! 解决方案是使用类型通配符:
1 | void printList(List<?> l) { |
---|
2 | for (Object o : l) |
---|
3 | System.out.println(o); |
---|
4 | } |
---|
上面代码中的问号是一个类型通配符。它读作“问号”。List<?> 是任何泛型 List 的父类型,所以您完全可以将 List<Object>、List<Integer> 或 List<List<List<Flutzpah>>> 传递给 printList()。