按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
言,所以这种特性是没有必要的。
然而,条件编译还有另一些非常有价值的用途。一种很常见的用途就是调试代码。调试特性可在开发过程中
使用,但在发行的产品中却无此功能。Alen Holub (holub。 )提出了利用包(package)来模仿条件
编译的概念。根据这一概念,它创建了C “断定机制”一个非常有用的Java 版本。之所以叫作“断定机
128
…………………………………………………………Page 130……………………………………………………………
制”,是由于我们可以说“它应该为真”或者“它应该为假”。如果语句不同意你的断定,就可以发现相关
的情况。这种工具在调试过程中是特别有用的。
可用下面这个类进行程序调试:
//: Assert。java
// Assertion tool for debugging
package 。bruceeckel。tools。debug;
public class Assert {
private static void perr(String msg) {
System。err。println(msg);
}
public final static void is_true(boolean exp) {
if(!exp) perr(〃Assertion failed〃);
}
public final static void is_false(boolean exp){
if(exp) perr(〃Assertion failed〃);
}
public final static void
is_true(boolean exp; String msg) {
if(!exp) perr(〃Assertion failed: 〃 + msg);
}
public final static void
is_false(boolean exp; String msg) {
if(exp) perr(〃Assertion failed: 〃 + msg);
}
} ///:~
这个类只是简单地封装了布尔测试。如果失败,就显示出出错消息。在第 9 章,大家还会学习一个更高级的
错误控制工具,名为“违例控制”。但在目前这种情况下,perr()方法已经可以很好地工作。
如果想使用这个类,可在自己的程序中加入下面这一行:
import 。bruceeckel。tools。debug。*;
如欲清除断定机制,以便自己能发行最终的代码,我们创建了第二个Assert 类,但却是在一个不同的包里:
//: Assert。java
// Turning off the assertion output
// so you can ship the program。
package 。bruceeckel。tools;
public class Assert {
public final static void is_true(boolean exp){}
public final static void is_false(boolean exp){}
public final static void
is_true(boolean exp; String msg) {}
public final static void
is_false(boolean exp; String msg) {}
} ///:~
现在,假如将前一个 import 语句变成下面这个样子:
import 。bruceeckel。tools。*;
程序便不再显示出断言。下面是个例子:
129
…………………………………………………………Page 131……………………………………………………………
//: TestAssert。java
// Demonstrating the assertion tool
package c05;
// ment the following; and unment the
// subsequent line to change assertion behavior:
import 。bruceeckel。tools。debug。*;
// import 。bruceeckel。tools。*;
public class TestAssert {
public static void main(String'' args) {
Assert。is_true((2 + 2) == 5);
Assert。is_false((1 + 1) == 2);
Assert。is_true((2 + 2) == 5; 〃2 + 2 == 5〃);
Assert。is_false((1 + 1) == 2; 〃1 +1 != 2〃);
}
} ///:~
通过改变导入的package,我们可将自己的代码从调试版本变成最终的发行版本。这种技术可应用于任何种
类的条件代码。
5。1。4 包的停用
大家应注意这样一个问题:每次创建一个包后,都在为包取名时间接地指定了一个目录结构。这个包必须存
在(驻留)于由它的名字规定的目录内。而且这个目录必须能从CLASSPATH 开始搜索并发现。最开始的时
候,package 关键字的运用可能会令人迷惑,因为除非坚持遵守根据目录路径指定包名的规则,否则就会在
运行期获得大量莫名其妙的消息,指出找不到一个特定的类——即使那个类明明就在相同的目录中。若得到
象这样的一条消息,请试着将package 语句作为注释标记出去。如果这样做行得通,就可知道问题到底出在
哪儿。
5。2 Java 访问指示符
针对类内每个成员的每个定义,Java 访问指示符 poublic,protected 以及private 都置于它们的最前面—
—无论它们是一个数据成员,还是一个方法。每个访问指示符都只控制着对那个特定定义的访问。这与C++
存在着显著不同。在C++中,访问指示符控制着它后面的所有定义,直到又一个访问指示符加入为止。
通过千丝万缕的联系,程序为所有东西都指定了某种形式的访问。在后面的小节里,大家要学习与各类访问
有关的所有知识。首次从默认访问开始。
5。2。1 “友好的”
如果根本不指定访问指示符,就象本章之前的所有例子那样,这时会出现什么情况呢?默认的访问没有关键
字,但它通常称为“友好”(Friendly )访问。这意味着当前包内的其他所有类都能访问“友好的”成员,
但对包外的所有类来说,这些成员却是“私有”(Private)的,外界不得访问。由于一个编译单元(一个文
件)只能从属于单个包,所以单个编译单元内的所有类相互间都是自动“友好”的。因此,我们也说友好元
素拥有“包访问”权限。
友好访问允许我们将相关的类都组合到一个包里,使它们相互间方便地进行沟通。将类组合到一个包内以后
(这样便允许友好成员的相互访问,亦即让它们“交朋友”),我们便“拥有”了那个包内的代码。只有我
们已经拥有的代码才能友好地访问自己拥有的其他代码。我们可认为友好访问使类在一个包内的组合显得有
意义,或者说前者是后者的原因。在许多语言中,我们在文件内组织定义的方式往往显得有些牵强。但在
Java 中,却强制用一种颇有意义的形式进行组织。除此以外,我们有时可能想排除一些类,不想让它们访问
当前包内定义的类。
对于任何关系,一个非常重要的问题是“谁能访问我们的‘私有’或private 代码”。类控制着哪些代码能
够访问自己的成员。没有任何秘诀可以“闯入”。另一个包内推荐可以声明一个新类,然后说:“嗨,我是
Bob 的朋友!”,并指望看到Bob 的“protected”(受到保护的)、友好的以及“private”(私有)的成
130
…………………………………………………………Page 132……………………………………………………………
员。为获得对一个访问权限,唯一的方法就是:
(1) 使成员成为“public”(公共的)。这样所有人从任何地方都可以访问它。
(2) 变成一个“友好”成员,方法是舍弃所有访问指示符,并将其类置于相同的包内。这样一来,其他类就
可以访问成员。
(3) 正如以后引入“继承”概念后大家会知道的那样,一个继承的类既可以访问一个 protected 成员,也可
以访问一个public 成员(但不可访问 private 成员)。只有在两个类位于相同的包内时,它才可以访问友好
成员。但现在不必关心这方面的问题。
(4) 提供“访问器/变化器”方法(亦称为“获取/设置”方法),以便读取和修改值。这是OOP 环境中最
正规的一种方法,也是 Java Beans 的基础——