第6章讲到了类库设计的权限访问问题,主要是通过Java提供的访问权限修饰词,让类库的使用者明白哪些是可用的,那些事不可用的。访问权限控制等级,从最大权限到最小权限依次为:public、protected、包访问权限(没有关键词)和private。作为一名类库设计员,你会尽可能将一切方法都定义为private,而仅向客户端程序员公开你愿意让他们使用的方法。
“6.1 包:库单元”,包内包含一组类,它们在单一的名字空间下被组织在一起。例如,在Java的标准发布中有一个工具库,它被组织在java.util名字空间之下。java.util中有一个叫做ArrayList的类,使用ArrayList的一种方式是用其全名java.util.ArrayList来指定。
publicclassFullQualification { publicstaticvoidmain(String[] args) { java.util.ArrayListlist=newjava.util.ArrayList(); } }
但是这会使得程序变得冗长,因此你可能向转而使用import关键字。如果你想要导入单个的类,可以在import语句中命名该类:
importjava.util.ArrayList; publicclassSingleImport { publicstaticvoidmain(String[] args) { ArrayListlist=newjava.util.ArrayList(); } }
要想使用java.util中的其他类,只需要使用“*”,就可以了:import java.util.*; 这就是Java提供的一种管理名字空间的机制。为什么要有名字空间这么个概念呢?假设你编写一个Stack类并安装到了一台机器上,而该机器上已经有了一个别人写的Stack类,我们该如何解决呢?由于名字之间的潜在冲突,在Java中对名字空间进行完全控制并为每一个类创建唯一的标识组合就成为了非常重要的事情了。上面列举的一些类的例子虽然没有指定包名,其实他们已经位于包中了:即未命名包或者默认包。私用关键字package关键字,可以指定一个类的包名:package access;
“6.2 创建独一无二的包名”这一小节告诉我们如何给package起一个有效的名字里让我们的类减少可能的冲突。按照惯例,package名称的第一部分是类的创建者的反顺序的Internet域名。比如cn.com.domain。第二部分可以把package名称分解为你机器上的一个目录。比如:business.directory。举个具体的例子来理解这一点,以我的域名是MindView.net为例。顺序倒过来就是net.mindview。为了演示个简单的例子,我们再创进一个simple的目录,我们的类就放在这个目录下,那么完整的包名如下:package net.mindview.simple;现在这个包名就可以作为下面两个文件的名字空间保护伞了:
packagenet.mindview.simple; publicclassVector { publicVector() { System.out.println("net.mindview.simple.Vector"); } } packagenet.mindview.simple; publicclassList { publicList() { System.out.println("net.mindview.simple.List"); } }
下面就可以写一个例子引入我们的类库并且使用它们了:
importnet.mindview.simple.*; publicclassLibTest { publicstaticvoidmain(String[] args) { Vectorv=newVector(); Listl=newList(); } }
有了上面的只是以后,我们就可以进入到“6.3 定制工具库”这一小节,创建自己的工具库来减少或消除重复的程序代码了。举个打印输出的例子:
packagenet.mindview.util; importjava.io.*; publicclassPrint { // Print with a newline: publicstaticvoidprint(Objectobj) { System.out.println(obj); } // Print a newline by itself: publicstaticvoidprint() { System.out.println(); } // Print with no line break: publicstaticvoidprintnb(Objectobj) { System.out.print(obj); } // The new Java SE5 printf() (from C): publicstaticPrintStreamprintf(Stringformat, Object... args) { returnSystem.out.printf(format, args); } } importstaticnet.mindview.util.Print.*; publicclassPrintTest { publicstaticvoidmain(String[] args) { print("Available from now on!"); print(100); print(100L); print(3.14159); } }
/* Output:
Available from now on!
100
100
3.14159
*/
上面的例子只是为了说明包名空间的使用,以后我们有新的工具类,都可以放在net.mindview.util类库中。