所有东西。到这一章结束时,大家应该可以深刻体会到 Java 访问控制的价值。
然而,组件库以及控制谁能访问那个库的组件的概念现在仍不是完整的。仍
存在这样一个问题:如何将组件绑定到单独一个统一的库单元里。这是通过 Java
的 package(打包)关键字来实现的,而且访问指示符要受到类在相同的包还是
在不同的包里的影响。所以在本章的开头,大家首先要学习库组件如何置入包里。
这样才能理解访问指示符的完整含义。
5.1 包:库单元
我们用 import 关键字导入一个完整的库时,就会获得“包”(Package)。例
如:
import java.util.*;
它的作用是导入完整的实用工具(Utility)库,该库属于标准 Java 开发工
具包的一部分。由于 Vector 位于 java.util 里,所以现在要么指定完整名称
“java.util.Vector
”
(可省略 import 语句),要么简单地指定一个“Vector
”
(因为 import 是默认的)。
若想导入单独一个类,可在 import 语句里指定那个类的名字:
import java.util.Vector;
现在,我们可以自由地使用 Vector。然而,java.util 中的其他任何类仍是
不可使用的。
之所以要进行这样的导入,是为了提供一种特殊的机制,以便管理“命名空
间”(Name Space)。我们所有类成员的名字相互间都会隔离起来。位于类 A 内的
一个方法 f()不会与位于类 B 内的、拥有相同“签名”(自变量列表)的 f()发生
冲突。但类名会不会冲突呢?假设创建一个 stack 类,将它安装到已有一个 stack
类(由其他人编写)的机器上,这时会出现什么情况呢?对于因特网中的 Java
应用,这种情况会在用户毫不知晓的时候发生,因为类会在运行一个 Java 程序
的时候自动下载。
正是由于存在名字潜在的冲突,所以特别有必要对 Java 中的命名空间进行
完整的控制,而且需要创建一个完全独一无二的名字,无论因特网存在什么样的
限制。
迄今为止,本书的大多数例子都仅存在于单个文件中,而且设计成局部(本
地)使用,没有同包名发生冲突(在这种情况下,类名置于“默认包”内)。这
是一种有效的做法,而且考虑到问题的简化,本书剩下的部分也将尽可能地采用
它。然而,若计划创建一个“对因特网友好”或者说“适合在因特网使用”的程
序,必须考虑如何防止类名的重复。
为 Java 创建一个源码文件的时候,它通常叫作一个“编辑单元”(有时也叫
作“翻译单元”)。每个编译单元都必须有一个以.java 结尾的名字。而且在编译
单元的内部,可以有一个公共(public)类,它必须拥有与文件相同的名字(包
括大小写形式,但排除.java 文件扩展名)。如果不这样做,编译器就会报告出
错。每个编译单元内都只能有一个 public 类(同样地,否则编译器会报告出错)。
那个编译单元剩下的类(如果有的话)可在那个包外面的世界面前隐藏起来,因
为它们并非“公共”的(非 public),而且它们由用于主 public 类的“支撑”
类组成。
编译一个.java 文件时,我们会获得一个名字完全相同的输出文件;但对
于.java 文件中的每个类,它们都有一个.class 扩展名。因此,我们最终从少量
评论