Java 5 之后提供泛型(Generics)支持,使用泛型可以最大限度地重用代码、保护类型的安全以及提高性能。泛型特性对 Java 影响最大是集合框架的使用。
对于 Java 5 之前程序员而言,使用集合经常会面临一个很尴尬的问题:放入一个种特定类型,但是取出时候全部是 Object 类型,于是在具体使用时候需要将元素强转换为特定类型。但是强制类型转换是有风险的,如果不进行判断就臆断进行类型转换会发生 ClassCastException 异常。
而泛型的引入可以将这些运行时异常提前到编译期暴露出来,这增强了类型安全检查。
自定义泛型类
public class Queue<T> { // 声明保存队列元素集合items private List<T> items; // 构造方法初始化是集合items public Queue() { this.items = new ArrayList<T>(); } /** * 入队方法 * @param item 参数需要入队的元素 */ public void queue(T item) { this.items.add(item); } /** * 出队方法 * @return 返回出队元素 */ public T dequeue(){ if (items.isEmpty()) { return null; } else { return this.items.remove(0); } } @Override public String toString() { return items.toString(); } }
T 是什么呢?T 表示类型参数,泛型就是类型参数化,处理的数据类型不是固定的,而是可以作为参数传入。
泛型的好处既然只使用普通类和 Object 就可以,而且泛型最后也转换为了普通类,那为什么还要用泛型呢?或者说,泛型到底有什么好处呢?泛型主要有两个好处:
❑ 更好的安全性。
❑ 更好的可读性。
语言和程序设计的一个重要目标是将 bug 尽量消灭在摇篮里,能消灭在写代码的时候,就不要等到代码写完程序运行的时候。只使用 Object,代码写错的时候,开发环境和编译器不能帮我们发现问题。
自定义泛型
自定义泛型接口与自定义泛型类类似,定义的方式完全一样。
泛型方法
在方法中也可以使用泛型,即方法的参数类型或返回值类型,可以用类型参数表示。实现代码如下:
// 限定类型参数为 Number public static <T> boolean isEquals(T a, T b) { return a.equals(b); }
另外,泛型的类型参数也可以限定一个边界,例如比较方法 isEquals() 只想用于数值对象大小的比较,实现代码如下:
// 限定类型参数为Number public static <T extends Number> boolean isEquals(T a, T b) { return a.equals(b); }
泛型通配符
泛型方法到底应该用通配符的形式还是加类型参数。两者到底有什么关系?
1)通配符形式都可以用类型参数的形式来替代,通配符能做的,用类型参数都能做。
2)通配符形式可以减少类型参数,形式上往往更为简单,可读性也更好,所以,能用通配符的就用通配符。
3)如果类型参数之间有依赖关系,或者返回值依赖类型参数,或者需要写操作,则只能用类型参数。
4)通配符形式和类型参数往往配合使用,比如,上面的 copy 方法,定义必要的类型参数,使用通配符表达依赖,并接受更广泛的数据类型。