- 写在前面的话
- 引言
- 第 1 章 对象入门
- 第 2 章 一切都是对象
- 第 3 章 控制程序流程
- 第 4 章 初始化和清除
- 第 5 章 隐藏实施过程
- 第 6 章 类再生
- 第 7 章 多形性
- 第 8 章 对象的容纳
- 第 9 章 违例差错控制
- 第 10 章 Java IO 系统
- 第 11 章 运行期类型鉴定
- 第 12 章 传递和返回对象
- 第 十三 章 创建窗口和程序片
- 第 14 章 多线程
- 第 15 章 网络编程
- 第 16 章 设计范式
- 第 17 章 项目
- 附录 A 使用非 JAVA 代码
- 附录 B 对比 C++和 Java
- 附录 C Java 编程规则
- 附录 D 性能
- 附录 E 关于垃圾收集的一些话
- 附录 F 推荐读物
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 扩展名。因此,我们最终从少量的.java 文件里有可能获得数量众多的.class 文件。如以前用一种汇编语言写过程序,那么可能已习惯编译器先分割出一种过渡形式(通常是一个.obj 文件),再用一个链接器将其与其他东西封装到一起(生成一个可执行文件),或者与一个库封装到一起(生成一个库)。但那并不是 Java 的工作方式。一个有效的程序就是一系列.class 文件,它们可以封装和压缩到一个 JAR 文件里(使用 Java 1.1 提供的 jar 工具)。Java 解释器负责对这些文件的寻找、装载和解释(注释①)。
①:Java 并没有强制一定要使用解释器。一些固有代码的 Java 编译器可生成单独的可执行文件。
“库”也由一系列类文件构成。每个文件都有一个 public 类(并没强迫使用一个 public 类,但这种情况最很典型的),所以每个文件都有一个组件。如果想将所有这些组件(它们在各自独立的.java 和.class 文件里)都归纳到一起,那么 package 关键字就可以发挥作用)。
若在一个文件的开头使用下述代码:
package mypackage;
那么 package 语句必须作为文件的第一个非注释语句出现。该语句的作用是指出这个编译单元属于名为 mypackage 的一个库的一部分。或者换句话说,它表明这个编译单元内的 public 类名位于 mypackage 这个名字的下面。如果其他人想使用这个名字,要么指出完整的名字,要么与 mypackage 联合使用 import 关键字(使用前面给出的选项)。注意根据 Java 包(封装)的约定,名字内的所有字母都应小写,甚至那些中间单词亦要如此。
例如,假定文件名是 MyClass.java。它意味着在那个文件有一个、而且只能有一个 public 类。而且那个类的名字必须是 MyClass(包括大小写形式):
package mypackage;
public class MyClass {
// . . .
现在,如果有人想使用 MyClass,或者想使用 mypackage 内的其他任何 public 类,他们必须用 import 关键字激活 mypackage 内的名字,使它们能够使用。另一个办法则是指定完整的名称:
mypackage.MyClass m = new mypackage.MyClass();
import 关键字则可将其变得简洁得多:
import mypackage.*;
// . . .
MyClass m = new MyClass();
作为一名库设计者,一定要记住 package 和 import 关键字允许我们做的事情就是分割单个全局命名空间,保证我们不会遇到名字的冲突——无论有多少人使用因特网,也无论多少人用 Java 编写自己的类。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论