![On Java:中文版·基础卷](https://wfqqreader-1252317822.image.myqcloud.com/cover/337/53256337/b_53256337.jpg)
3.7.1 名称可见性
所有的编程语言都有一个问题,那就是对名称的控制。比如,你在程序的一个模块中使用了一个名称,有人在其他模块中也使用了这个名称,那么应该如何区分两者?又该如何避免两者之间的“冲突”?对于C语言来说,这个问题尤其令人感到头疼,因为程序中经常充斥着各种名称,维护成本极高。而C++的类(Java中类的设计参考了C++)则是将函数放置于类的内部,因此一个类的函数名不会与其他类的同名函数发生冲突。但是,C++依然允许使用全局数据和全局函数,所以潜在的冲突也依然存在。为了解决这个问题,C++使用额外的关键字引入了命名空间的概念。
而Java通过一种新颖的方法解决了此问题。为了能够清晰地描述库的名称,Java语言的设计者所使用的方法是将你的互联网域名反转使用。因为域名是唯一的,所以一定不会冲突。举例来说,如果域名是ituring.com,那么foibles库的名称就是com.ituring.utility.foibles。而反转的域名之后的几个“.”实际上描述了子目录的结构。
在Java 1.0和Java 1.1里,按照约定俗成的惯例,类似com、edu、org、net等扩展名的首字母都是大写,所以你会看到类似Com.ituring.utility.foibles这样的名称。然而在Java 2的开发过程中,Java的设计者发现这种方法会引发一些问题。于是从那之后一直到现在,包名都变成了小写字母。
这种机制确保了所有文件都有对应的命名空间,同时文件里定义的类都具有唯一对应的标识符。因此,Java语言就避免了命名冲突的问题。
使用反转的URL来定义命名空间是一种全新的尝试,而在此之前没有其他语言使用过此方案。此外,Java语言还有其他一些与之类似的解决特定问题的方案。不难想象,如果一种新特性没有经过充分验证的话,将来出现问题的概率会很大。如果我们在实际编程阶段应用了该特性,一旦出现问题就回天乏术了(有些问题甚至严重到需要从语言中去掉某些特性)。
将命名空间和利用反转的URL所生成的文件路径相关联会带来一个问题,不过这个问题并不是程序的bug,而是会对我们管理源代码带来一些挑战。比如我们想要使用com.ituring.utility.foibles这个命名空间,那么我就需要创建名为com和ituring的空文件夹,其目的只是为了与反转的URL相对应。而这种做法还将引入一个你之后在Java工程中会遇到的情况:通过空文件夹层层嵌套而形成的这种文件夹结构,其作用不只是为了对应反转的URL,同时也会获取一些其他的信息。实际上,这些冗长的文件夹路径通常用于保存一些表明文件夹内容的数据。如果你仍然希望这些文件夹能够发挥其设计之初的功效,会发现尝试的结果不仅仅是让人沮丧,简直可以说是让人崩溃。因此在编写工程级别的Java代码时,基本上你不得不使用那些精心设计的IDE以管理层层嵌套的代码,比如IntelliJ IDEA等。实际上,IDE通常都会帮助你创建和管理这些深度嵌套的空文件夹。
由于这种深不见底的文件夹结构会让你在开始学习语言时就想要使用大型IDE,而我并不想让你承受这种额外的负担和困扰,因此本书所有章节的代码示例都使用了浅显易懂的结构,即子文件夹名与其(英文版)章节名保持一致。只有一个小问题,那就是我偶尔需要和那些按照深度结构设计的工具斗争一番罢了。