Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Update 07_How_to_Define_ArrayList.md
  • Loading branch information
maskleo authored Apr 15, 2018
commit bade58a73f9228ff39445b5902d7ac82f6dfcea8
30 changes: 23 additions & 7 deletions ch06/07_How_to_Define_ArrayList.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,31 @@
《《《 [返回首页](../README.md) <br/>
《《《 [上一节](06_The_Principle_of_Indecent_Exposure.md)

## 如何定义 ArrayList

我们在其他地方争辩说,通常最好使用列表而不是使用数组。有一些地方这不合适。在极少数情况下,出于效率或兼容性的原因,您将需要使用数组。另外,当然,你需要使用数组来实现 `ArrayList` 本身。在这里,我们将 `ArrayList` 的实现作为一种模型,在极少情况下需要使用数组。这些实现需要谨慎编写,因为它们必然涉及使用未经检查的强制转换。我们将看到实施中的“不雅暴露原则”和“广告真相原理”。
我们在其他地方争辩说,通常最好使用列表而不是使用数组。有一些地方这不合适。在极少数情况下,出于效率或兼容性的原因,您将需要使用数组。另外,当然,你需要使
用数组来实现 `ArrayList` 本身。在这里,我们将 `ArrayList` 的实现作为一种模型,在极少情况下需要使用数组。这些实现需要谨慎编写,因为它们必然涉及使用未经
检查的强制转换。我们将看到实施中的“不雅暴露原则”和“广告真相原理”。

例 `6-2` 显示了实现。我们通过从 `AbstractList` 中继承派生了 `ArrayList`。从这个类派生的类只需要定义四个方法,即 `get`,`set`,`add` 和 `remove`;其他方法是根据这些定义的。我们还指出类实现了 `RandomAccess`,表明类的客户端使用 `get` 比使用列表迭代器更有效。
例 `6-2` 显示了实现。我们通过从 `AbstractList` 中继承派生了 `ArrayList`。从这个类派生的类只需要定义四个方法,即 `get`,`set`,`add` 和 `remove`;其
他方法是根据这些定义的。我们还指出类实现了 `RandomAccess`,表明类的客户端使用 `get` 比使用列表迭代器更有效。

该类用两个私有字段表示包含 `E` 类型元素的列表:包含列表长度的 `int` 类型大小,以及包含列表元素的类型为 `E []` 的 `arr`。该数组的长度必须至少等于大小,
但最后可能会有其他未使用的元素。

该类用两个私有字段表示包含E类型元素的列表:包含列表长度的 `int` 类型大小,以及包含列表元素的类型为 `E []` 的 `arr`。该数组的长度必须至少等于大小,但最后可能会有其他未使用的元素。
有两个地方分配数组的新实例,一个在类的初始化器中,另一个在增加数组容量的方法中(这又从 `add` 方法中调用)。在这两个地方,数组都被分配为一个
`Object []`,并且未勾选的类型转换为 `E []`。

有两个地方分配数组的新实例,一个在类的初始化器中,另一个在增加数组容量的方法中(这又从 `add` 方法中调用)。在这两个地方,数组都被分配为一个 `Object []`,并且未勾选的类型转换为 `E []`。
包含数组的字段是私人的是非常重要的;否则将违反广告真理原则和不雅暴露原则。这违反了广告中的真理原则,因为 `E` 可能被绑定到 `Object` 以外的类型(如
`String`)。这会违反不雅暴露原则,因为 `E` 可能会绑定到不是可保留类型的类型(例如 `List<Integer>`)。但是,这些原则都没有违反,因为该数组并非公开的:
它存储在私人领域,没有指向数组的指针从类中逃脱。我们可以称之为封闭门背后的任何原则。

包含数组的字段是私人的是非常重要的;否则将违反广告真理原则和不雅暴露原则。这违反了广告中的真理原则,因为 `E` 可能被绑定到 `Object` 以外的类型(如 `String`)。这会违反不雅暴露原则,因为 `E` 可能会绑定到不是可保留类型的类型(例如 `List<Integer>`)。但是,这些原则都没有违反,因为该数组并非公开的:它存储在私人领域,没有指向数组的指针从类中逃脱。我们可以称之为封闭门背后的任何原则。
我们在这里定义 `ArrayList` 的方式接近 `Sun` 发布的源代码中的实际定义。最近,该库的共同作者 `Neal Gafter` 认为他使用了糟糕的风格 - 如果声明私有数组的
类型为 `Object []`,并且在从数组中检索元素时使用强制类型(`E`)会更好。对于这一点,有些话要说,尽管对于我们在这里使用的风格也有一些要说的,这可以最大限
度地减少对未经检查的演员的需求。

我们在这里定义 `ArrayList` 的方式接近 `Sun` 发布的源代码中的实际定义。最近,该库的共同作者 `Neal Gafter` 认为他使用了糟糕的风格 - 如果声明私有数组的类型为 `Object []`,并且在从数组中检索元素时使用强制类型(`E`)会更好。对于这一点,有些话要说,尽管对于我们在这里使用的风格也有一些要说的,这可以最大限度地减少对未经检查的演员的需求。
`toArray` 的方法确实会公开返回一个数组,但它使用了第 `6.5` 节中所述的技巧,依照广告中的真理原则。和之前一样,有一个参数数组,如果它不足以容纳集合,则使
用反射来分配具有相同指定类型的新数组。这个实现类似于我们前面看到的实现,除了可以使用更高效的 `arraycopy` 例程将私有数组复制到公用数组中以返回。

`toArray` 的方法确实会公开返回一个数组,但它使用了第 `6.5` 节中所述的技巧,依照广告中的真理原则。和之前一样,有一个参数数组,如果它不足以容纳集合,则使用反射来分配具有相同指定类型的新数组。这个实现类似于我们前面看到的实现,除了可以使用更高效的 `arraycopy` 例程将私有数组复制到公用数组中以返回。
《《《 [下一节](08_Array_Creation_and_Varargs.md) <br/>
《《《 [返回首页](../README.md)