类的访问权限

在 java 中,访问权限修饰词也可以用于确定在某个程序库中的类哪些对于该库的使用者是可用的。如果你希望某个类可以为某个客户端程序员所用,你就可以通过把关键字 public作用于整个类的定义来达到目的。这样做甚至可以控制客户端程序员是否能创建一个该类的对象。为了控制某个类的访问权限,修饰词必须出现于关键字 class 之前。因此你可以声明:
public class Widget {
现在如果你的类库的名字是 mylib,那么任何客户端程序员都可以通过下面的声明访问Widget
import mylib.Widget;或import mylib.*;然而,这里还有一些额外的限制:
1.每个编译单元(文件)都只能有一个 public 类。这表示,每个编译单元都有一个单一的公共接口,用 public 类来表现。该接口可以按照你的希望去包含众多的支持包访问权限的类。如果在某个编译单元内有一个以上的 public类,编译器就会向你给出一个出错的信息。
2.public 类的名称必须完全与含有该编译单元的文件名相匹配,包括大小写。所以对于 Widget 而言,文件的名称必须是 Widget.java,而不是widget.java 或 WIDGET.java。如果不匹配,你将会再次得到编译时间出错的提示。
3.虽然不是很常用,但编译单元内完全不带 public 类也是可能的。在这种情况下,你可以随意对文件命名。如果你获取了一个在 mylib 内部的类,用来完成 Widget 或是其他在 mylib 中的 public类所要执行的任务,
将会出现什么样的情况呢?你不想自找麻烦去为客户端程序员创建说明文档,而且你认为不久你可能会想要完全改变原有方案并将旧版本一起删除,代之以一种不同的版本。为了保留此灵活性,你需要确保客户端程序员不会依赖于你隐藏在mylib 之中的任何特定实现细节。为了达到这一点,你只需将关键字 public 从类中拿掉,它就拥有了包访问权限。(这个类只可以用于该包之中。)在你创建一个包访问权限的类时,它仍旧在将该类的域声明为 private 的时才具有意义——你应尽可能地总是将域指定为是私有的——但是通常来说,将与类(包访问权)相同的访问权限赋予方法也是很合理的。既然一个包访问权限的类通常只能被用于包内,那么如果对你有强制要求,在此种情况下,编译器会告诉你,你只需要将这样的类的方法设定为public 就可以了。
请注意,类既不可以是private的(这样会使得除该类之外再无其他类可以访问它)也不可以是protected的 5 。所以对于类的访问权限,你仅有两个选择:包访问权或是public。如果你不希望其他任何人对该类拥有访问权限,你可以把所有的构造器都指定为private,从而阻止任何人创建该类的对象,但是有一个例外,就是在该类的static成员内部可以创建。下面是一示例:
//: c05:Lunch.java
// Demonstrates class access specifiers. Make a class
// effectively private with private constructors:
class Soup {
private Soup() {}
// (1) Allow creation via static method:
public static Soup makeSoup() {
return new Soup();
}
// (2) Create a static object and return a reference
// upon request.(The "Singleton" pattern):
private static Soup ps1 = new Soup();
public static Soup access() {
return ps1;
}
public void f() {}
}
class Sandwich { // Uses Lunch
void f() { new Lunch(); }
}
// Only one public class allowed per file:
public class Lunch {
void test() {
// Can't do this! Private constructor:
//! Soup priv1 = new Soup();
Soup priv2 = Soup.makeSoup();
Sandwich f1 = new Sandwich();
Soup.access().f();
}
} ///:~
5
到目前为止,绝大多数方法均返回 void 或是原始类型,所以此定义:
public static Soup access() {
return ps1;
}
初看起来可能有点令人迷惑不解。方法名称(access)前面的词告知了该方法返回的东西。到目前为止,这个方法经常被用作为 void,所以它不返回任何东西。但是你也可以返回一个对象引用,示例中就是这种情况。这个方法返回了一个对 Soup 类的对象的引用。Soup 类展示了如何通过将所有的构造器指定为 private 的方法来阻止直接创建某个类的实例。
请一定要牢记如果你没有显示地至少创建一个构造器的话,就会帮你创建一个缺省构造器(不带有任何参数的构造器)。如果我们自己编写了缺省的构造器,那么就不会自动创建它了。如果把该构造器指定为 private,那么就谁也无法创建该类的对象了。但是现在别人该怎样使用这个类呢?上面的例子就给出了两个选择:第一,创建一个 static 方法,来生成一个新的 Soup 并返回一个对它的引用。如果你想要在返回引用之前在 Soup 上作一些额外的工作,或是如果你想要记录到底创建了多少个 Soup 的对象(可能要限制其数量),这种做法将会是大有裨益的。第二个选择用到了一个设计模式(design pattern),该模式在 www.BruceEckel.com网站 Thinking in Patterns (with Java)一书中有所介绍。这种特定的模式被称为“singleton”,这是因为你始终只能创建它的单一的一个对象。Soup 类的对象是作为 Soup的一个 static private 成员而生成的,所以有且仅有一个,而且你除非是通过 public方法 access( ),否则你是无法访问到它的。正如前面所提到的,如果你没能为类访问权限指定一个访问修饰符,它就会缺省得到包访问权限。这就意味着该类的对象可以由包内任何其他类来创建,但在包外则是不行的。(一定要记住,相同目录下的所有不具有明确 package 声明的文件,都被视作是该目录下缺省包的一部分。)然而,如果该类的某个 static 成员是 public 的话,则客户端程序员仍旧可以调用该 static 成员,哪怕是他们并不能生成该类的对象。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值