From 15ea9cd233da1c1db837db24f466f6699579078d Mon Sep 17 00:00:00 2001 From: sjsdfg <736777445@qq.com> Date: Sun, 1 Dec 2019 14:11:36 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E7=AC=AC=2029=20=E6=9D=A1?= =?UTF-8?q?=E6=A0=87=E7=82=B9=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/notes/29. 优先考虑泛型.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/notes/29. 优先考虑泛型.md b/docs/notes/29. 优先考虑泛型.md index 01c75ed..485523f 100644 --- a/docs/notes/29. 优先考虑泛型.md +++ b/docs/notes/29. 优先考虑泛型.md @@ -137,7 +137,7 @@ public E pop() { } ``` -  两种消除泛型数组创建的技术都有其追随者。 第一个更可读:数组被声明为 `E[]` 类型,清楚地表明它只包含 `E` 实例。 它也更简洁:在一个典型的泛型类中,你从代码中的许多点读取数组; 第一种技术只需要一次转换(创建数组的地方),而第二种技术每次读取数组元素都需要单独转换。 因此,第一种技术是优选的并且在实践中更常用。 但是,它确实会造成堆污染(heap pollution)(详见第 32 条):数组的运行时类型与编译时类型不匹配(除非 `E` 碰巧是 `Object`)。 这使得一些程序员非常不安,他们选择了第二种技术,尽管在这种情况下堆的污染是无害的。 +  两种消除泛型数组创建的技术都有其追随者。 第一个更可读:数组被声明为 `E[]` 类型,清楚地表明它只包含 `E` 实例。 它也更简洁:在一个典型的泛型类中,你从代码中的许多点读取数组;第一种技术只需要一次转换(创建数组的地方),而第二种技术每次读取数组元素都需要单独转换。 因此,第一种技术是优选的并且在实践中更常用。 但是,它确实会造成堆污染(heap pollution)(详见第 32 条):数组的运行时类型与编译时类型不匹配(除非 `E` 碰巧是 `Object`)。 这使得一些程序员非常不安,他们选择了第二种技术,尽管在这种情况下堆的污染是无害的。   下面的程序演示了泛型 `Stack` 类的使用。 该程序以相反的顺序打印其命令行参数,并将其转换为大写。 对从堆栈弹出的元素调用 `String` 的 `toUpperCase` 方法不需要显式强制转换,而自动生成的强制转换将保证成功: @@ -155,7 +155,7 @@ public static void main(String[] args) {   上面的例子似乎与条目 28 相矛盾,条目 28 中鼓励使用列表优先于数组。 在泛型类型中使用列表并不总是可行或可取的。 Java 本身生来并不支持列表,所以一些泛型类型(如 `ArrayList`)必须在数组上实现。 其他的泛型类型,比如 `HashMap`,是为了提高性能而实现的。 -  绝大多数泛型类型就像我们的 `Stack` 示例一样,它们的类型参数没有限制:可以创建一个 `Stack,Stack`,`Stack>` 或者其他任何对象的 `Stack` 引用类型。 请注意,不能创建基本类型的堆栈:尝试创建 `Stack` 或 `Stack` 将导致编译时错误。 这是 Java 泛型类型系统的一个基本限制。 可以使用基本类型的包装类(详见第 61 条)来解决这个限制。 +  绝大多数泛型类型就像我们的 `Stack` 示例一样,它们的类型参数没有限制:可以创建一个 `Stack, Stack`,`Stack>` 或者其他任何对象的 `Stack` 引用类型。 请注意,不能创建基本类型的堆栈:尝试创建 `Stack` 或 `Stack` 将导致编译时错误。 这是 Java 泛型类型系统的一个基本限制。 可以使用基本类型的包装类(详见第 61 条)来解决这个限制。   有一些泛型类型限制了它们类型参数的允许值。 例如,考虑 `java.util.concurrent.DelayQueue`,它的声明如下所示: @@ -163,7 +163,7 @@ public static void main(String[] args) { class DelayQueue implements BlockingQueue ``` -  类型参数列表(``)要求实际的类型参数 `E` 是 `java.util.concurrent.Delayed` 的子类型。 这使得 DelayQueue 实现及其客户端可以利用 `DelayQueue` 元素上的 `Delayed` 方法,而不需要显式的转换或 `ClassCastException` 异常的风险。 类型参数 `E` 被称为限定类型参数。 请注意,子类型关系被定义为每个类型都是自己的子类型[JLS,4.10],因此创建 `DelayQueue` 是合法的。 +  类型参数列表(``)要求实际的类型参数 `E` 是 `java.util.concurrent.Delayed` 的子类型。 这使得 `DelayQueue` 实现及其客户端可以利用 `DelayQueue` 元素上的 `Delayed` 方法,而不需要显式的转换或 `ClassCastException` 异常的风险。 类型参数 `E` 被称为限定类型参数。 请注意,子类型关系被定义为每个类型都是自己的子类型[JLS,4.10],因此创建 `DelayQueue` 是合法的。   总之,泛型类型比需要在客户端代码中强制转换的类型更安全,更易于使用。 当你设计新的类型时,确保它们可以在没有这种强制转换的情况下使用。 这通常意味着使类型泛型化。 如果你有任何现有的类型,应该是泛型的但实际上却不是,那么把它们泛型化。 这使这些类型的新用户的使用更容易,而不会破坏现有的客户端(条目 26)。