4.7.4 包的作用域

    前面已经接触过访问修饰符public和private。标记为public的部分可以被任意的类使用;标记为private的部分只能被定义它们的类使用。如果没有指定public或private,这个部分(类、方法或变量)可以被同一个包中的所有方法访问。

    下面再仔细地看一下例4-2中的程序。在这个程序中,没有将Employee类定义为公有类,因此只有在同一个包(在此是默认包)中的其他类可以访问,例如EmployeeTest。对于类来说,这种默认是合乎情理的。但是,对于变量来说就有些不适宜了,因此变量必须显式地标记为private,不然的话将默认为包可见。显然,这样做会破坏封装性。问题主要出于人们经常忘记键入关键字private。在java.awt包中的Window类就是一个典型的示例。java.awt包是JDK提供的部分源代码:

  
  
  
  
  1. public class Window extends Container 
  2.     String warningString; 
  3.     .... 

    请注意,这里的warningString变量不是private!这意味着java.awt包中的所有类的方法都可以访问该变量,并将它设置为任意值(例如,“Trust me!”)。实际上,只有Window类的方法访问它,因此应该将它设置为私有变量。我们猜测可能是程序员匆忙之中忘记键入private修饰符了(为防止程序员内疚,我们没有说出他的名字,感兴趣的话,可以查看一下源代码)。

    注释:奇怪的是,这个问题至今还没有得到纠正,即使我们在这本书的8个版本中已经指出了这一点。很明显,类库的实现者并没有读这本书。不仅如此,这个类还增加了一些新域,其中大约一半也不是私有的。

    这真的会成为一个问题吗?答案是:视具体情况而定。在默认情况下,包不是一个封闭的实体。也就是说,任何人都可以向包中添加跟多的类。当然,有敌意或低水平的程序员很可能利用包的可见性添加一些具有改变变量功能的代码。例如,在Java程序设计语言的早期版本中,只需要将下列这条语句放在类文件的开头,就可以很容易地将其他类混入java.awt包中:

  
  
  
  
  1. package java.awt; 

然后,把结果类文件放置在类路径某处的java/awt子目录下,就可以访问java.awt包的内部了。使用这一手段,可以对警告框进行设置。

    从1.2版开始,JDK的实现者修改了类加载器,明确地禁止加载哦那个湖自定义的、包名以“java.”开始的类!当然,用户自定义的类无法从这种保护中受益。然而,可以通过包密封(package sealing)机制来解决将各个包混杂在一起的问题。如果将一个包密封起来,就不能再向这个包添加类了。在第10章中,将介绍制作包含密封包的JAR文件的方法。

你可能感兴趣的:(Java核心技术I)