第五章 泛型
自 Java 5 以来,泛型一直是 Java 语言的一部分。在泛型出现之前,从集合中读取的每个对象都必须进行强制转换。如果有人不小心插入了错误类型的对象,强制类型转换可能在运行时失败。对于泛型,你可以告知编译器在每个集合中允许哪些类型的对象。编译器会自动为你进行强制转换与插入的操作,如果你试图插入类型错误的对象,编译器会在编译时告诉你。这就产生了更安全、更清晰的程序,但是这些好处不仅仅局限于集合,而且也是有代价的。这一章会告诉你如何最大限度地扬长避短。
26. 不要使用原始类型
首先,有几个术语。一个类或接口,它的声明有一个或多个类型参数(type parameters ),被称之为泛型类或泛型接口[JLS,8.1.2,9.1.2]。 例如,List 接口具有单个类...
27. 消除非检查警告
使用泛型编程时,会看到许多编译器警告:未经检查的强制转换警告,未经检查的方法调用警告,未经检查的参数化可变长度类型警告以及未经检查的转换警告。 你使用泛型获得的经验越多,获得的警告越少,但不...
28. 列表优于数组
数组在两个重要方面与泛型不同。 首先,数组是协变的(covariant)。 这个吓人的单词意味着如果 Sub 是 Super 的子类型,则数组类型 Sub[] 是数组类型 Super[] 的...
29. 优先考虑泛型
参数化声明并使用 JDK 提供的泛型类型和方法通常不会太困难。 但编写自己的泛型类型有点困难,但值得努力学习。 考虑条目 7 中的简单堆栈实现: // Object-based coll...
30. 优先使用泛型方法
正如类可以是泛型的,方法也可以是泛型的。 对参数化类型进行操作的静态工具方法通常都是泛型的。 集合中的所有“算法”方法(如 binarySearch 和 sort)都是泛型的。 编写泛型...
31. 使用限定通配符来增加 API 的灵活性
如条目 28 所述,参数化类型是不变的。换句话说,对于任何两个不同类型的 Type1 和 Type2,List<Type1> 既不是 List<Type2> 的子类型也不是其父类型。尽管 L...
32. 合理地结合泛型和可变参数
在 Java 5 中,可变参数方法(详见第 53 条)和泛型都被添加到平台中,所以你可能希望它们能够正常交互; 可悲的是,他们并没有。 可变参数的目的是允许客户端将一个可变数量的参数传递给一...
33. 优先考虑类型安全的异构容器
泛型的常见用法包括集合,如 Set<E> 和 Map<K,V> 和单个元素容器,如 ThreadLocal<T> 和 AtomicReference<T>。 在所有这些用途中,它都是参数化的...