第六章 访问权限控制(下)
6.2 Java访问权限修饰词
public、protected、private这几个Java访问权限修饰词在使用时,是置于每个类中每个成员的定义之前的,无论它是一个城还是一个方法,每个访问权限修饰词仅控制它所修饰的特定定义的访问权限。如果不提供任何访问权限修饰词,则意味着它是包访问权限。
6.2.1 包访问权限
默认访问权限没有任何关键字,但通常是指包访问权限,这意味着当前的包中的所有其他类对那个成员都有访问权限,但对于这个包之外的所有类,这个成员却是private。由于一个编译单元只能隶属于一个包,所有经由包访问权限,处于同一个编译单元中的所有类彼此之间都是可访问的。
取的对某成员的访问权的途径是:
1、使该成员public
2、通过不加访问权限修饰词并将其他类置于同一个包内的方式给成员赋予包访问权
3、继承
4、提供访问器和变异器(getter和setter)以读取和改变数值。
6.2.2 public:接口访问权限
如下:
public class Cookie {
public Cookie() {
System.out.println(“Cookie constructor”);
}
void bite() {
System.out.println(“bite”);
}
}
现在如果创建一个使用Cookie的程序:
Cookie x = new Cookie();
//! x.bite();
第一句代码可以执行,而第二句则会报错,因为它的构造器是public而类也是public的,但是由于bite()方法只向包内的类提供访问权,所以bite()成员在这里是没法访问的。
6.2.3 private:你无法访问
关键字private的意思是,除了包含该成员的类之外,其他任何类都无法访问这个成员,由于处于同一个包内的其他类是不可以访问private成员的,因此这等于是自己隔离了自己。默认的包访问权限通常已经提供了充足的隐藏措施,使用类的客户端程序员无法访问权限成员。
这里有一个示例:
class Sundae {
private Sundae() {}
static Sundae makeASundae() {
return new Sundae();
}
}
public class IceCream {
public static void main(String[] args) {
Sundae x = Sundae.makeASundae();
}
}
这是一个说明private有用武之地的示例,可以阻止别人直接访问某个特定的构造器,不能直接通过构造器来创建Sundae对象,而必须使用makeASundae()方法来到达这个目的。
6.2.4 protected:继承访问权限
关键字protected处理的是继承的概念,通过继承可以利用一个现有的类(基类),然后将新成员添加到该现有类中而不必碰现有类。为了从现有类中继承,需要声明新类extends(扩展)了一个现有类:
class Foo extends Bar { }
如果创建了一个新包,并从另一个包中继承类,那么唯一可以访问的成员就是源包的public成员。有时基类的创建者会希望有某个特定的成员把对它的访问权限赋予派生类而不是所有类,这就需要protected来完成这一工作。protected也提供包访问权限,也就是说相同包内的其他类可以访问protected元素。
6.3 接口和实现
访问权限的控制通常被称为是集体实现的隐藏,把数据和方法包装进类中,以及具体实现的隐藏,常共同被称作封装,其结果是一个同事带有特征和行为的数据类型。
出于两个很重要的原因,访问权限控制将权限的边界划在了数据类型的内部。第一个原因是要设定客户端程序员可不可以使用的界限。第二个原因就是将接口和具体的实现分离,如果结构是用于一组程序之中,而客户端程序员除了可以向接口发送消息之外什么也不可以做的话,那么就可以随意更改所有不是public的东西。
6.4 类的访问权限
在Java中,访问权限修饰词也可以用于确定库中的哪些类对于该库的使用者是可用的,如果希望某个类可以为某个客户端程序员所用,就可以把关键字public作用域整个类的定义来达到目的。
为了控制某个类的访问权限,修饰词必须出现于关键字class之前,因此可以这样子声明:
public class Widget {
这里还有一些额外的限制:
1、每个编译单元都只能有一个public类,这表示每个编译单元都有单一的公共接口,用public类来表现,该接口可以按要求包含众多的支持包访问权限的类,如果在某个编译单元内有一个以上的public类,编译器就会给出出错信息。
2、public类的名称必须完全与含有该编译单元的文件名相匹配,包括大小写。对于Widget而言,文件名称必须是Widg.java。
3、虽然不太常用,但是编译单元内完全不带public类也是有可能的,这种情况下可以随意对文件命名。
类是不可以private的,也是不可以protected的,所以对于类的访问权限,只有两个选择:包访问权或者public。如果不希望其他任何人对该类拥有访问权限,可以把所有的构造器都指定为private从而阻止任何人创建该类的对象。但是你可以在该类的static成员内部创建。