|
5 | 5 |
|
6 | 6 | 我们已经看到,在许多方面集合优于数组: |
7 | 7 |
|
8 | | - - 集合比数组提供更精确的输入。 通过列表,可以编写 `List<T>`,`List <? extends T>` 或 `List <? super T>`; 而对于数组,只能写 `T []`,这对应于 |
9 | | -列表的三个选项中的第二个。 更精确的打字可以在编译时检测到更多的错误,而不是运行时。 这使编码,调试,测试和维护更容易,并且还提高了效率。 (见 `2.5` |
| 8 | +- 集合比数组提供更精确的输入。 通过列表,可以编写 `List<T>`,`List <? extends T>` 或 `List <? super T>`; 而对于数组,只能写 `T []`,这对应于列 |
| 9 | +表的三个选项中的第二个。 更精确的打字可以在编译时检测到更多的错误,而不是运行时。 这使编码,调试,测试和维护更容易,并且还提高了效率。 (见 `2.5` |
10 | 10 | 节) |
11 | 11 |
|
12 | | - - 集合比数组更灵活。 集合提供了各种表示形式,包括数组,链表,树和散列表,而数组具有固定的表示形式,这些库为集合提供了比数组更多的方法和便利算法。 |
| 12 | +- 集合比数组更灵活。 集合提供了各种表示形式,包括数组,链表,树和散列表,而数组具有固定的表示形式,这些库为集合提供了比数组更多的方法和便利算法。 |
13 | 13 | (见 `2.5` 节) |
14 | 14 |
|
15 | | - - 集合可能具有任何类型的元素,而数组只能具有可定义类型的组件。 在创建数组时,必须遵守广告中的真理原则 - 具体化类型必须符合静态类型 - 以及不雅暴露 |
16 | | -原则 - 从不公开暴露组件不具有可确定类型的数组。 (见第 `6.5` 节和第 `6.6` 节)。 |
| 15 | +- 集合可能具有任何类型的元素,而数组只能具有可定义类型的组件。 在创建数组时,必须遵守广告中的真理原则 - 具体化类型必须符合静态类型 - 以及不雅暴露原则 |
| 16 | +- 从不公开暴露组件不具有可确定类型的数组。 (见第 `6.5` 节和第 `6.6` 节)。 |
17 | 17 |
|
18 | 18 | 回想起来,在Java 5中有几个地方避免使用数组可能会改进设计: |
19 | 19 |
|
20 | | - - 变长参数(可变参数)由一个数组表示,因此受到相同的限制。 如果可变参数绑定到不可确定类型的实参,则会发出一个通用数组创建警告(这引发了与未检查警 |
21 | | -告相同的担忧)。 例如,函数 `Arrays.asList` 需要一个可变参数。 使用此函数返回 `List<Integer>` 类型的结果没有任何困难,但创建类型为 |
| 20 | +- 变长参数(可变参数)由一个数组表示,因此受到相同的限制。 如果可变参数绑定到不可确定类型的实参,则会发出一个通用数组创建警告(这引发了与未检查警告相 |
| 21 | +同的担忧)。 例如,函数 `Arrays.asList` 需要一个可变参数。 使用此函数返回 `List<Integer>` 类型的结果没有任何困难,但创建类型为 |
22 | 22 | `List<List <Integer >>` 或类型为 `List <E>` 的结果存在问题。 如果列表优先于数组,则不会出现此问题。 (见 `6.8` 节) |
23 | 23 |
|
24 | | - - Java库中的某些方法的签名违反了不雅曝光原则: |
| 24 | +- Java库中的某些方法的签名违反了不雅曝光原则: |
25 | 25 |
|
26 | | - ```java |
27 | | - TypeVariable<Class<T>>[] java.lang.Class.getTypeParameters() |
28 | | - TypeVariable<Method>[] java.lang.Reflect.Method.getTypeParameters() |
29 | | - ``` |
| 26 | +```java |
| 27 | +TypeVariable<Class<T>>[] java.lang.Class.getTypeParameters() |
| 28 | +TypeVariable<Method>[] java.lang.Reflect.Method.getTypeParameters() |
| 29 | +``` |
30 | 30 |
|
31 | 31 | 调用这些方法的代码有可能违反伴随泛型的铸铁保证:即使编译器没有发出未经检查的警告,它也可能在代码中没有显式强制转换的情况下引发类转换异常。 (编译库时 |
32 | 32 | 发出了警告 - 错误地忽略了)。同样,如果列表优先于数组,则不会出现此问题。 (见 `6.6` 节) |
33 | 33 |
|
34 | 34 | `Java 5` 设计中一些复杂性的一个原因是为使用数组提供了很好的支持。 回想起来,选择更简单的设计可能会更好,但是使得数组的使用并不方便: |
35 | 35 |
|
36 | | - - 数组必须使用可定义类型的组件创建,因此为尽量减少这种限制,尝试尽可能地使可保存类型的概念成为一般。 如果设计人员愿意限制实现类型的概念,他们可以 |
37 | | -通过包含原始类型(如 `List`)来简化它,但不包括带有无限通配符的类型(如 `List<?>`)。 如果他们这样做了,可重用类型就会成为未参数化类型的代名词(即原 |
38 | | -始类型,原始类型和没有类型参数的类型)。这种变化将简化实例测试中允许的类型。 考虑以下三个测试: |
| 36 | +- 数组必须使用可定义类型的组件创建,因此为尽量减少这种限制,尝试尽可能地使可保存类型的概念成为一般。 如果设计人员愿意限制实现类型的概念,他们可以通过 |
| 37 | +包含原始类型(如 `List`)来简化它,但不包括带有无限通配符的类型(如 `List<?>`)。 如果他们这样做了,可重用类型就会成为未参数化类型的代名词(即原始类 |
| 38 | +型,原始类型和没有类型参数的类型)。这种变化将简化实例测试中允许的类型。 考虑以下三个测试: |
39 | 39 |
|
40 | | - ```java |
41 | | - obj instanceof List |
42 | | - obj instanceof List<?> |
43 | | - obj instanceof List<? extends Object> |
44 | | - ``` |
| 40 | +```java |
| 41 | + obj instanceof List |
| 42 | + obj instanceof List<?> |
| 43 | + obj instanceof List<? extends Object> |
| 44 | +``` |
45 | 45 | |
46 | 46 | 目前,前两个是允许的,但第三个不是。 通过限制建议,只允许第一个限制。 可以说,这可能更容易理解。 这也符合对类标记的处理,因为目前允许 `List.class`, |
47 | 47 | 但 `List <?>.class` 是非法的。 |
48 | 48 |
|
49 | | - - 目前,数组创建仅限于可调整类型的数组。 但是允许声明一个不可确认类型的数组,或者将其转换为不可确定的数组类型,代价是在代码中的某处未经检查的警 |
50 | | -告。 正如我们所看到的,这样的警告违反了与泛型相伴随的铸铁保证,并且即使源代码不包含转换,也可能导致类转换错误。 |
| 49 | +- 目前,数组创建仅限于可调整类型的数组。 但是允许声明一个不可确认类型的数组,或者将其转换为不可确定的数组类型,代价是在代码中的某处未经检查的警告。 |
| 50 | +正如我们所看到的,这样的警告违反了与泛型相伴随的铸铁保证,并且即使源代码不包含转换,也可能导致类转换错误。 |
51 | 51 |
|
52 | 52 | 一个更简单和更安全的设计将取缔任何不可接受类型的数组(使用刚才描述的更简单形式的可重写类型)。 这种设计意味着我们永远不能声明一个 `E []` 类型的数组, |
53 | 53 | 其中 `E` 是一个类型变量。 |
|
58 | 58 | 此更改也意味着您无法为集合(或类似方法)的 `toArray` 方法分配泛型类型。 代替: |
59 | 59 |
|
60 | 60 | ```java |
61 | | - public <T> T[] toArray(T[] arr) |
| 61 | + public <T> T[] toArray(T[] arr) |
62 | 62 | ``` |
63 | 63 |
|
64 | 64 | 我们会有: |
65 | 65 |
|
66 | 66 | ```java |
67 | | - public Object[] toArray(Object[] arr) |
| 67 | + public Object[] toArray(Object[] arr) |
68 | 68 | ``` |
69 | 69 | |
70 | 70 | 并且这种方法的许多用途都需要显式地输出结果。 这确实会让用户的生活变得更加尴尬,但可以说,简单性和安全性的提高是值得的。 |
71 | 71 |
|
72 | | - - 前面的更改意味着通常会使用优先于数组的列表。 通过允许 `Java` 程序员将 `l [i]` 编写为 `l.get(i)` 的缩写,并将 `l [i] = v` 作为 `l.put(i,v)` |
73 | | -的缩写,可以使列表的使用变得更容易。 (有些人喜欢这种“语法糖”,而有些人则认为它是“句法老鼠毒”。) |
| 72 | +- 前面的更改意味着通常会使用优先于数组的列表。 通过允许 `Java` 程序员将 `l [i]` 编写为 `l.get(i)` 的缩写,并将 `l [i] = v` 作为 `l.put(i,v)` 的 |
| 73 | +缩写,可以使列表的使用变得更容易。 (有些人喜欢这种“语法糖”,而有些人则认为它是“句法老鼠毒”。) |
74 | 74 |
|
75 | 75 | 其中一些变化仍然可以以后向兼容的方式进行调整。我们在 `6.8` 节中提到,可能需要添加基于列表而不是数组的第二种可变参数形式。 允许使用缩写来使列表索引看 |
76 | 76 | 起来像数组索引可以很容易地被合并到未来的 `Java` 版本中。 |
|
83 | 83 |
|
84 | 84 | 《《《 [下一节](10_Summing_Up.md) <br/> |
85 | 85 | 《《《 [返回首页](../README.md) |
86 | | - |
0 commit comments