友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!阅读过程发现任何错误请告诉我们,谢谢!! 报告错误
一世书城 返回本书目录 我的书架 我的书签 TXT全本下载 进入书吧 加入书签

Java编程思想第4版[中文版](PDF格式)-第53章

按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!




  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 的基础——具体情况会在第 13 章介绍。  



5。2。2 public :接口访问  



使用public 关键字时,它意味着紧随在public 后面的成员声明适用于所有人,特别是适用于使用库的客户 

程序员。假定我们定义了一个名为 dessert 的包,其中包含下述单元(若执行该程序时遇到困难,请参考第 

3 章 3。1。2 小节“赋值”):  

  

//: Cookie。java  

// Creates a library  

package c05。dessert;  

  

public class Cookie {  

  public Cookie() {   

   System。out。println(〃Cookie constructor〃);   

  }  

  void foo() { System。out。println(〃foo〃); }  

} ///:~  

  

请记住,Cookie。java 必须驻留在名为dessert 的一个子目录内,而这个子目录又必须位于由 CLASSPATH 指 

定的C05 目录下面(C05 代表本书的第 5 章)。不要错误地以为 Java 无论如何都会将当前目录作为搜索的起 

点看待。如果不将一个“。”作为CLASSPATH 的一部分使用,Java 就不会考虑当前目录。  

现在,假若创建使用了 Cookie 的一个程序,如下所示:  

  

//: Dinner。java  

// Uses the library  

import c05。dessert。*;  

  

public class Dinner {  

  public Dinner() {  

   System。out。println(〃Dinner constructor〃);  

  }  

  public static void main(String'' args) {  

    Cookie x = new Cookie();  

    //! x。foo(); // Can't access  

  }  

} ///:~  

  

就可以创建一个Cookie 对象,因为它的构建器是 public 的,而且类也是public 的(公共类的概念稍后还会 

进行更详细的讲述)。然而,foo()成员不可在 Dinner。java 内访问,因为foo()只有在 dessert包内才是 

 “友好”的。  

  

1。 默认包  

大家可能会惊讶地发现下面这些代码得以顺利编译——尽管它看起来似乎已违背了规则:  



                                                                                        131 


…………………………………………………………Page 133……………………………………………………………

  

//: Cake。java  

// Accesses a class in a separate   

// pilation unit。  

  

class Cake {  

  public static void main(String'' args) {  

    Pie x = new Pie();  

    x。f();  

  }  

} ///:~  

  

在位于相同目录的第二个文件里:  

  

//: Pie。java  

// The other class  

  

class Pie {  

  void f() { System。out。println(〃Pie。f()〃); }  

} ///:~  

  

最初可能会把它们看作完全不相干的文件,然而Cake 能创建一个 Pie 对象,并能调用它的 f()方法!通常的 

想法会认为Pie 和f()是“友好的”,所以不适用于 Cake 。它们确实是友好的——这部分结论非常正确。但 

它们之所以仍能在 Cake。java 中使用,是由于它们位于相同的目录中,而且没有明确的包名。Java 把象这样 

的文件看作那个目录“默认包”的一部分,所以它们对于目录内的其他文件来说是“友好”的。  



5。2。3 private :不能接触!  



private 关键字意味着除非那个特定的类,而且从那个类的方法里,否则没有人能访问那个成员。同一个包 

内的其他成员不能访问private 成员,这使其显得似乎将类与我们自己都隔离起来。另一方面,也不能由几 

个合作的人创建一个包。所以 private 允许我们自由地改变那个成员,同时毋需关心它是否会影响同一个包 

内的另一个类。默认的“友好”包访问通常已经是一种适当的隐藏方法;请记住,对于包的用户来说,是不 

能访问一个“友好”成员的。这种效果往往能令人满意,因为默认访问是我们通常采用的方法。对于希望变 

成public (公共)的成员,我们通常明确地指出,令其可由客户程序员自由调用。而且作为一个结果,最开 

始的时候通常会认为自己不必频繁使用private 关键字,因为完全可以在不用它的前提下发布自己的代码 

 (这与C++是个鲜明的对比)。然而,随着学习的深入,大家就会发现private 仍然有非常重要的用途,特 

别是在涉及多线程处理的时候(详情见第 14 章)。  

下面是应用了private 的一个例子:  

  

//: IceCream。java  

// Demonstrates 〃private〃 keyword  

  

class Sundae {  

  private Sundae() {}  

  static Sundae makeASundae() {   

    return new Sundae();   

  }  

}  

  

public class IceCream {  

  public static void main(String'' args) {  

    //! Sundae x = new Sundae();  

    Sundae x = Sundae。makeASundae();  



                                                                                           132 


…………………………………………………………Page 134……………………………………………………………

  }  

} ///:~  

  

这个例子向我们证明了使用private
返回目录 上一页 下一页 回到顶部 0 0
未阅读完?加入书签已便下次继续阅读!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!