4.1 包:库单元
当编写一个Java源代码文件时,此文件通常被称为编译单元。每个编译单元都必须有一个文件后缀名.java,而在编译单元内则可以有一个public类,该类的名称必须与文件的名称相同(包括大小写,但不包括后缀)。每个编译单元只能有一个public类,否则编译器不会接受。如果在该编译单元之中还有额外的类的话,在包之外是无法看见这些类的,这是因为它们不是public类,而且它们主要用来为public类提供支持。
4.1.1 代码组织
当编译一个.java文件,在.java文件中每个类都会有一个输出文件,而该输出文件的名称与.java文件中每个类的名称相同,只是多了一个后缀名.class。因此,在编译少量.java文件之后,会得到大量的.class文件。编译型语言,编译器产生一个中间文件(通常是obj),然后再与通过连接器(创建可执行文件)或类库产生器产生的其他同类文件捆绑在一起的情况。但这并不是java的工作方式。Java可运行程序是一组可以打包并压缩为一个Java文档文件(JAR)的.class文件。Java解释器负责这些文件的查找、装载与解释。
类库实际上是一组类文件。其中每个文件都有一个public类,以及任意数量的非public类。因此每个文件都有一个构件。如果希望这些构件(每一个都有它们自己独立的.java和.class文件)从属于同一个群组,就可以使用关键字package。
4.1.2 独一无二的包名
一个包从未真正将被打包的东西包装成单一的文件,并且可以由许多.class文件构成,那么情况就有点复杂。为了避免这种情况的发生,一种做法就是将特定包所有.class都置于一个目录下。也就是说,利用操作系统的层次文件结构解决这一问题。
将所有文件收入一个子目录中还可以解决另外两个问题:怎样创建独一无二的名称以及怎样查找有可能隐藏于目录结构中某处的类。这些任务是通过将.class文件所在的路径位置编码成package的名称来实现的。按照惯例,package名称的第一部分是类的创建者的反顺序的Internet域名。如果你依照它,域名是独一无二的,因此你的package名称也将是独一无二的,也就不会出现名称冲突问题了。
此技巧的第二部分是把package名称分解为机器上的一个目录。所以当Java程序运行并且需要加载.class文件的时候,它就可以确定.class文件在目录上所处的位置。
Java解释器的运行过程如下:首先,找出环境变量(可以通过操作系统设置,也可以通过安装程序设置)。CLASSPATH包含一个或多个目录,用作查找.class文件的根目录。从根目录开始,解释器获取包的名称并将美国句点替换成\,以从CLASSPATH根中产生一个路径名称。得到的路径会与CLASSPATH的各个不同的项相连接,解释器就在这些目录中查找你所要创建的类名称相关的.class文件。
4.1.3 使用包的忠告
无论何时创建包,都已经在给定包名称的时候隐含地指定了目录结构。这个包必须位于其名称所指定的目录之中,而且该目录必须是在以CLASSPATH开始的目录中科院查询到的。除非遵守“包名称对应目录路径”的规则,否则将会收到许多出乎意料的运行时信息,告知无法找到特定的类,哪怕这个类就在同一个目录中。
4.2 Java访问权限修饰词
如果不提供任何访问权限修饰词,则意味着它是“包访问权限”。
4.2.1 包访问权限
有时候也表示成friendly。这意味着当前包中所有其他类对那个成员有访问权限,但对于这个包之外的所有类,这个成员却是private。由于一个编译单元(即一个文件),只能隶属一个包,所以经由包访问权限,处于同一个编译单元中的所有类彼此间都是自动可访问的。
包访问权限允许将包内所有的相关的类组合起来,以使他们彼此之间可以轻松地相互作用。当把类组织起来放进一个包内,也就给它们的包访问权限的成员赋予了相互访问的权限,就拥有了该包的代码。
类控制着哪些代码有权访问自己的成员。取得某成员的访问权的途径是:
1.使该成员为public。
2.通过不加访问权限修饰词并将其他类放置于同一个包内的方式给成员赋予包访问权。
3.继承而来的类可以访问public和protected成员。
4.提供get/set方法。对OOP而言,这是最优雅的方式,也是JavaBeans的基本原理。
4.3 接口与实现
访问权限的控制常被称为具体实现的隐藏。把数据和方法包装进类中,以及具体实现的隐藏,共同被称为封装。其结果是一个同时带有特征和行为的数据类型。
访问权限控制将边界划在了数据类型的内部。原因是要设定客户端程序员可以使用和不可以使用的界限。可以在结果中建立自己的内部机制,而不必担心客户端程序员会讲内部机制当做他们可以使用接口的一部分。
4.4 类的访问权限
1.每个编译单元都只能有一个public类。这表示,每个编译单元都有单一的额公共接口,用public类实现。该接口可以按要求包含众多的支持包访问权限的类。如果在某个编译单元内有一个以上的public类,编辑器就沪给出错误信息。
2.public类的名称必须完全与含有该编译单元的文件名相匹配,包括大小写。