Appearance
包是一种组织类的方式。包中可以包含任意数量的类,这些类的用途相关或有继承关系。
如果程序较小,且使用的类不多,则根本没必要了解包。但随着程序越来越复杂,将使用大量通过继承彼此相关的类,这时将它们组织成包的好处将显现出来。
由于以下几个主要的原因,包很在用。
包让你能够将类组织成单元。在硬盘中,您通过文件夹来组织文件和应用程序,而包让您能够将类编组,让生个程序只使用所需的类。
包减少了名称冲突还来的问题。随着Java类数量的增长,类第一名的可能性也不断增加。当您在同一个程序中使用多组类时,可能发生名称冲突,从而导致错误。包让您能够引用所需的类,即使这个类与另一个包中的某个类同名。
包让您能够大面积地保护类、变量和方法,而不是分别对每个类进行保护。
包可用于唯一地标识类
本书一直在使用包。每当您使用命令import或通过全名来引用类时(如java.util.Sting Tokenizer),都使用了包。
要使用包中的类,可采用下述三种机制之一。
如果要使用的类位于包java.lang中(如System或Date),可以通过类名来引用它。Java.lang包中的类将自动被导入到所有的程序中。
如果要使用的类位于其他包中,可以通过全名——包括包名(如java.awt.Font)来引用它。
对于频繁使用的类,可以导入单个类或整个包。类或包被导入后,只需通过名称便可引用相应的类。
没有被指定其所属包的类将放到一个未命名的默认包中。要引用这种类,只需要使用其名称即可。
要引用其他包中的类,可以使用全名:包名或类名。在这种情况下,无须将类或包导入:
java.awt.Font text = new java.awt.Font();
对于程序中只使用一两次的类,使用全名可能更合适。然而,如果需要使用某个类多次,应将其导入以减少输入量。然而,没有理由不使用import,因此您可能决定采取本书的做法,总是将要使用的类导入,这样类名将更短,代码也更容易理解。
**impo****ort****声明**
要导入包中的类,可以使用import声明。可以导入单个类,如:
import java.util.ArrayLiat;
也可以导入包中的所有类,方法是使用星号*代替类名,如:
import java.awt.*;
在import 语句中,星号只能用来代替类名,而不能用于导入多个名称类似的包。
例如,Java类库包含java.util、java.uti.jar和java.util.prefs等包,您不能使用下面的语句来导入这3个包:
import java.util.*;
上述语句只导入包java.util。要导入这三个包,必须 使用下述语句:
import java.util.*;
import java.util.jar.*;
import java.util.prefs.*;
另外不能指定类名的一部分(例如,使用L*导入所有以L打头的类)。使用import 声明时,要么使用星号导入整个包,要么导入其中的一个类。
import 声明位于文件开头,在任何类定义之前 ,但在包定义之后。
分别导入各个类还是导入整个包在很大程度上是一种编码风格。导入整个包并不会降低程序的速度,也不会增加其长度,只有代码中实际使用的那些类才会被加载。必须承认,导入整个包的确使阅读代码的人难以知道类来自于何方。
注意:关键字import 只是告诉Java编译器到哪里去查找类,而不会导入任何类的代码。
import 语句还可用于通过名称引用类中的常量。
通常,在引用常量时,必须在前面加上类名,如Color.black,Math.PI和File.separator。
通过使用import static语句,可以通过更简短的方法引用指定类中的常量。关键字import static后面跟一个接口(类)的名称和一个星号,例如:
import static java.lang.Math.*;
上述语句使得只需使用名称便能够引用Math类中的常量,如E和PI。下面是一个例子,利用了这种特性:
**类名冲突**
导入类或包后,通常可以通过类名来引用它,而不用提供包名。但在下述情况下,必须更明确地指出:在不同包中有多个名称相同的类。
在进行数据库编程时便可能发生名称冲突。这种编程可能涉及java.util和java.sql包,它们都包含一个名为Date的类。
如果要在读写数据库中数据的类时用这两个包,可以使用下述语句导入它们:
import java.sql.*;
import java.util.*;
导入这两个包后,如果像您下面那样在引用Date类时没有指定包名,将发生编译器错误:
Date now = new Date();
这是因为Java编译器无法判断语句中引用的是哪个Date类,因此必须像下面那样指定包名:
java.util.Date = new java.util.Date();
**创建自己的包**
在Java中,创建包来组织类并不比创建类更复杂。
**选择包名**
首先要确定包名。Oracle推荐Java开发人员使用受自己控制的Internet域名来给包命名。为得到包名,将域名中的元素颠倒过来,使用域名的最后一部分成为第一部分,然后是倒数第二部分。
这种规则确保其他Java一发人员不会提供同名的包,如果他们也遵循这种规则。
另一个约定是,包名不使用大写字母,以便将其与类名区别开来,例如,内置类String的全名为java.lang.String,从中很容易区分包名和类名。
**创建文件夹结构**
创建包的第二步是在硬盘上创建一个与包名对应的文件夹结构,名称的每部分对应于一个不同的文件夹。,对于包org.cadenhead.rss,需要创建一个名为org的文件夹,然后在该文件夹中创建一个名为cadenhead的文件夹,再在cadenhead中创建一个名为rss的文件夹,最后将这个包中的类存储到rss文件夹中。
在NetBeansk ,当您将类加入包中时,将自动创建相应的文件夹,并将源代码和类文件存储在正确的子文件夹中。您只需要指定包名。
如本书目录结构:
**将类加入到包中**
创建包的最后一步是将类加入到包中,即在类文件中的import语句和类声明之前 添加一条语句——package声明和完整的包名,如下所示:
package org.cadenhead.rss;
package声明必须是源代码文件的第一行(注释和空行除外)
**包和类访问控制**
如果没有指定限定符,则类的访问控制为默认级别,即可被同一个包中的其它类使用,但在包外不可见,也不可用。通过包保护的类被隐藏在其所在的包中,不能通过名称来导入或引用它。
要让类在包外可见并可导入,可在其定义中加入限定符public,使之为公有的。
public calss Visible {
//
}
被声明为公有的类可被包外的类导入。
注意,在import语句中使用星号时,导入的只是包中的公有类。推出的殴打仍被隐藏,只能被包中的其他类使用。
为什么要将类隐藏在包中?原因也在类中隐藏变量和方法相同:创建只有您的实现代码可以使用的类和行为,或者限制程序接口,从而最大限度降低修改还来的影响。设计类时,就应该对整个包进行全盘考虑,确定哪些类应声明为仅有的。哪些类应隐藏。
要创建一个优秀的包,必须 定义一组小型的、清晰的公有类和方法,供其他类使用,然后使用隐藏的支持类来实现它们。