5. 隐藏实施过程

5. 隐藏实施过程,第1张

5. 隐藏实施过程

Version:1.0 StartHTML:0000000163 EndHTML:0000064363 StartFragment:0000045775 EndFragment:0000064323 SourceURL:file:///Z:/thinking_in_java/java_reveiwv2.docx

5.1 包:库单元

import java.util.*;

它的作用是导入完整的实用工具(Utility)库,该库属于标准Java 开发工具包的一部分。由于Vector 位于

java.util 里,所以现在要么指定完整名称“java.util.Vector”(可省略 import 语句),要么简单地指定

一个“Vector”(因为 import 是默认的)。

例如,假定文件名是MyClass.java。它意味着在那个文件有一个、而且只能有一个 public 类。而且那个类

的名字必须是MyClass(包括大小写形式):

package mypackage;

public class MyClass {

// . . .

现在,如果有人想使用 MyClass,或者想使用 mypackage 内的其他任何 public 类,他们必须用import 关键字激活 mypackage 内的名字,使它们能够使用。另一个办法则是指定完整的名称:

mypackage.MyClass m = new mypackage.MyClass();

import 关键字则可将其变得简洁得多:

import mypackage.*;

// . . .

MyClass m = new MyClass();

作为一名库设计者,一定要记住package 和 import 关键字允许我们做的事情就是分割单个全局命名空间,保证我们不会遇到名字的冲突

5.2 Java访问指示符

Public,protected,private

5.2.1 友好的

如果根本不指定访问指示符,就象本章之前的所有例子那样,这时会出现什么情况呢?默认的访问没有关键字,但它通常称为“友好”(Friendly)访问。这意味着当前包内的其他所有类都能访问“友好的”成员

但对包外的所有类来说,这些成员却是“私有”(Private)的,外界不得访问。由于一个编译单元(一个文

件)只能从属于单个包,所以单个编译单元内的所有类相互间都是自动“友好”的。因此,我们也说友好元

素拥有“包访问”权限。

为获得对一个访问权限,唯一的方法就是:

(1) 使成员成为“public”(公共的)。这样所有人从任何地方都可以访问它。

(2) 变成一个“友好”成员,方法是舍弃所有访问指示符,并将其类置于相同的包内。这样一来,其他类就

可以访问成员。

(3) 正如以后引入“继承”概念后大家会知道的那样,一个继承的类既可以访问一个 protected 成员,也可

以访问一个 public 成员(但不可访问 private 成员)。只有在两个类位于相同的包内时,它才可以访问友好成员。但现在不必关心这方面的问题。

5.2.2 public

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

如果在不同的package内,可以访问一个package内的public的方法,但是不能访问private或者protected或者没有声明访问权限的方法。

5.2.3 private:不能接触

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

内的其他成员不能访问 private 成员,这使其显得似乎将类与我们自己都隔离起来。另一方面,也不能由几个合作的人创建一个包。所以 private 允许我们自由地改变那个成员,同时毋需关心它是否会影响同一个包内的另一个类。默认的“友好”包访问通常已经是一种适当的隐藏方法;请记住,对于包的用户来说,是不能访问一个“友好”成员的。这种效果往往能令人满意,因为默认访问是我们通常采用的方法。对于希望变

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

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

(这与 C++是个鲜明的对比)。然而,随着学习的深入,大家就会发现private 仍然有非常重要的用途,特别是在涉及多线程处理的时候(详情见第 14 章)。Private还可以防止对这个类的继承。

5.2.4 protected:友好的一种

protected 关键字为我们引入了一种名为“继承”的概念,它以现有的类为基础,并在其中加入新的成员,

同时不会对现有的类产生影响——我们将这种现有的类称为“基础类”或者“基本类”(base Class)。亦可改变那个类现有成员的行为。对于从一个现有类的继承,我们说自己的新类“扩展”(extends)了那个现有的类

  1. 基类的protected成员是包内可见的,并且对子类可见;
  2. 若子类与基类不在同一包中,那么在子类中,子类实例可以访问其从基类继承而来的protected方法(通过自己创建的对象访问),而不能直接访问基类实例的protected方法。

5.3 接口与实现

我们通常认为访问控制是“隐藏实施细节”的一种方式。将数据和方法封装到类内后,可生成一种数据类

型,它具有自己的特征与行为。但由于两方面重要的原因,访问为那个数据类型加上了自己的边界。第一个原因是规定客户程序员哪些能够使用,哪些不能。我们可在结构里构建自己的内部机制,不用担心客户程序员将其当作接口的一部分,从而自由地使用或者“滥用”。

这个原因直接导致了第二个原因:我们需要将接口同实施细节分离开。若结构在一系列程序中使用,但用户除了将消息发给public 接口之外,不能做其他任何事情,我们就可以改变不属于 public 的所有东西(如

“友好的”、protected 以及private),同时不要求用户对他们的代码作任何修改。

我们现在是在一个面向对象的编程环境中,其中的一个类(class)实际是指“一类对象”,就象我们说“鱼

类”或“鸟类”那样。从属于这个类的所有对象都共享这些特征与行为。“类”是对属于这一类的所有对象

的外观及行为进行的一种描述。

5.4 类访问

(1) 每个编译单元(文件)都只能有一个public 类。每个编译单元有一个公共接口的概念是由那个公共类表达出来的。根据自己的需要,它可拥有任意多个提供支撑的“友好”类。但若在一个编译单元里使用了多个

public 类,编译器就会向我们提示一条出错消息。

(2) public 类的名字必须与包含了编译单元的那个文件的名字完全相符,甚至包括它的大小写形式。所以对

于Widget 来说,文件的名字必须是Widget.java,而不应是 widget.java 或者WIDGET.java。同样地,如果

出现不符,就会报告一个编译期错误。

(3) 可能(但并常见)有一个编译单元根本没有任何公共类。此时,可按自己的意愿任意指定文件名。

如果已经获得了mylib 内部的一个类,准备用它完成由Widget 或者 mylib 内部的其他某些public 类执行的任务,此时又会出现什么情况呢?我们不希望花费力气为客户程序员编制文档,并感觉以后某个时候也许会进行大手笔的修改,并将自己的类一起删掉,换成另一个不同的类。为获得这种灵活处理的能力,需要保证没有客户程序员能够依赖自己隐藏于mylib 内部的特定实施细节。为达到这个目的,只需将public 关键字从类中剔除即可,这样便把类变成了“友好的”(类仅能在包内使用)。

注意不可将类设成 private(那样会使除类之外的其他东西都不能访问它),也不能设成 protected(注释

④)。因此,我们现在对于类的访问只有两个选择:“友好的”或者 public。若不愿其他任何人访问那个

类,可将所有构建器设为private。这样一来,在类的一个static 成员内部,除自己之外的其他所有人都无

法创建属于那个类的一个对象(注释⑤)。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5685442.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存