diff --git a/docs/book/07-Implementation-Hiding.md b/docs/book/07-Implementation-Hiding.md index d6376b2..c291627 100644 --- a/docs/book/07-Implementation-Hiding.md +++ b/docs/book/07-Implementation-Hiding.md @@ -15,12 +15,53 @@ 为了解决这一问题,Java 提供了访问修饰符供类库开发者指明哪些对于客户端程序员是可用的,哪些是不可用的。访问控制权限的等级,从"最大权限"到"最小权限"依次是:**public**,**protected**,包访问权限(没有关键字)和 **private**。根据上一段的内容,你可能会想,作为一名类库设计者,你会尽可能将一切都设为 **private**,仅向客户端程序员暴露你愿意他们使用的方法。这就是你通常所做的,尽管这与使用其他语言(尤其是 C)编程和访问不受任何限制的人们的直觉相违背。 +然而,构建类库的概念和对类库组件的访问控制仍然不完善。其中仍然存在问题就是如何将类库组件捆绑到一个内聚到类库单元中。Java 中通过 package 关键字加以控制,类是在相同包下还是不同包下会影响访问修饰符。所以在这章开始,你将会学习如何将类库组件置于同一个包下,之后你就能明白访问修饰符的全部含义。 + ## 包的概念 +包内包含一组类,它们被组织在一个单独的命名空间下。 + +例如,标准 Java 发布中有一个工具库,它被组织在 **java.util** 命名空间下。**java.util** 中含有一个类,叫做 **ArrayList**。使用 **ArrayList** 的一种方式是用其全名 **java.util.ArrayList**。 + +```java +// hiding/FullQualification.java + +public class FullQualification { + public static void main(String[] args) { + java.util.ArrayList list = new java.util.ArrayList(); + } +} +``` + +这种方式使得程序冗长乏味,因此你可以换一种方式,使用 **import** 关键字。如果需要导入某个类,就需要在 **import** 语句中声明: + +```java +// hiding/SingleImport.java + +import java.util.ArrayList; + +public class SingleImport { + public static void main(String[] args) { + ArrayList list = new ArrayList(); + } +} +``` + +现在你就可以不加限定词,直接使用 **ArrayList** 了。但是对于 **java.util** 包下的其他类,你还是不能用。要导入其中所有的类,只需使用 ***** ,就像本书中其他示例那样: +```java +import java.util.* +``` + +之所以使用导入,是为了提供一种管理命名空间的机制。所有类名之间都是相互隔离的。类 **A** 中的方法 `f()` 不会与类 **B** 中具有相同签名的方法 `f()` 冲突。但是如果类名冲突呢?假设你创建了一个 **Stack** 类,打算安装在一台已经有别人所写的 **Stack** 类的机器上,该怎么办呢?这种类名的潜在冲突,正是我们需要在 Java 中对命名空间进行完全控制的原因。为了解决冲突,我们为每个类创建一个唯一标识符组合。 + +到目前为止的大部分示例都只存在单个文件,并为本地使用的,所以尚未收到包名的干扰。但是,这些示例其实已经位于包中了,叫做"未命名"包或默认包。这当然是一种选择,为了简单起见,本书其余部分会尽可能采用这种方式。但是,如果你打算为相同机器上的其他 Java 程序创建友好的类库或程序时,就必须仔细考虑以防类名冲突。 + +一个 Java 源代码文件称为一个*编译单元*(有时也称*翻译单元*)。每个编译单元的文件名后缀必须是 **.java**。在编译单元中可以有一个 **public** 类,它的类名必须与文件名相同(包括大小写,但不包括后缀名 **.java**)。 + ## 访问权限修饰符