ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
## [包的概念](https://lingcoder.gitee.io/onjava8/#/book/07-Implementation-Hiding?id=%e5%8c%85%e7%9a%84%e6%a6%82%e5%bf%b5) 包内包含一组类,它们被组织在一个单独的*命名空间*(namespace)下。 例如,标准 Java 发布中有一个工具库,它被组织在**java.util**命名空间下。**java.util**中含有一个类,叫做**ArrayList**。使用**ArrayList**的一种方式是用其全名**java.util.ArrayList**。 ~~~ // hiding/FullQualification.java public class FullQualification { public static void main(String[] args) { java.util.ArrayList list = new java.util.ArrayList(); } } ~~~ 这种方式使得程序冗长乏味,因此你可以换一种方式,使用**import**关键字。如果需要导入某个类,就需要在**import**语句中声明: ~~~ // hiding/SingleImport.java import java.util.ArrayList; public class SingleImport { public static void main(String[] args) { ArrayList list = new ArrayList(); } } ~~~ 现在你就可以不加限定词,直接使用**ArrayList**了。但是对于**java.util**包下的其他类,你还是不能用。要导入其中所有的类,只需使用**\***,就像本书中其他示例那样: ~~~ import java.util.* ~~~ 之所以使用导入,是为了提供一种管理命名空间的机制。所有类名之间都是相互隔离的。类**A**中的方法`f()`不会与类**B**中具有相同签名的方法`f()`冲突。但是如果类名冲突呢?假设你创建了一个**Stack**类,打算安装在一台已经有别人所写的**Stack**类的机器上,该怎么办呢?这种类名的潜在冲突,正是我们需要在 Java 中对命名空间进行完全控制的原因。为了解决冲突,我们为每个类创建一个唯一标识符组合。 到目前为止的大部分示例都只存在单个文件,并为本地使用的,所以尚未受到包名的干扰。但是,这些示例其实已经位于包中了,叫做“未命名”包或*默认包*(default package)。这当然是一种选择,为了简单起见,本书其余部分会尽可能采用这种方式。但是,如果你打算为相同机器上的其他 Java 程序创建友好的类库或程序时,就必须仔细考虑以防类名冲突。 一个 Java 源代码文件称为一个*编译单元(compilation unit)*(有时也称*翻译单元(translation unit)*)。每个编译单元的文件名后缀必须是**.java**。在编译单元中可以有一个**public**类,它的类名必须与文件名相同(包括大小写,但不包括后缀名**.java**)。每个编译单元中只能有一个**public**类,否则编译器不接受。如果这个编译单元中还有其他类,那么在包之外是无法访问到这些类的,因为它们不是**public**类,此时它们为主**public**类提供“支持”类 。