《Thinking in Java》学习笔记——第五章:隐藏实施过程

第五章:隐藏实施过程
“进行面向对象的设计时,一项基本的考虑是:如何将发生变化的东西与保持不变的东西分隔开。”
为解决这个问题,Java 推出了“访问指示符”的概念,允许库创建者声明哪些东西是客户程序员可以使用的,哪些是不可使用的。这种访问控制的级别在“最大访问”和“最小访问”的范围之间,分别包括:public,“友好的”(无关键字),protected 以及private。这是通过Java 的package(打包)关键字来实现的,而且访问指示符要受
到类在相同的包还是在不同的包里的影响。所以在本章的开头,大家首先要学习库组件如何置入包里。这样才能理解访问指示符的完整含义。
5.1 包,库单元
为Java 创建一个源码文件的时候,它通常叫作一个“编辑单元”(有时也叫作“翻译单元”)。每个编译单元都必须有一个以.java 结尾的名字。而且在编译单元的内部,可以有一个公共(public)类,它必须拥有与文件相同的名字(包括大小写形式,但排除.java 文件扩展名)。如果不这样做,编译器就会报告出错。每个编译单元内都只能有一个public 类(同样地,否则编译器会报告出错)。那个编译单元剩下的类(如果有的话)可在那个包外面的世界面前隐藏起来,因为它们并非“公共”的(非public),而且它们由用于主public 类的“支撑”类组成。
一个有效的程序就是一系列.class 文件,它们可以封装和压缩到一个JAR 文件里(使用Java 1.1 提供的jar 工具)。Java 解释器负责对这些文件的寻找、装载和解释。
“库”也由一系列类文件构成。每个文件都有一个public 类(并没强迫使用一个public 类,但这种情况最很典型的),所以每个文件都有一个组件。如果想将所有这些组件(它们在各自独立的.java 和.class 文件里)都归纳到一起,那么package 关键字就可以发挥作用。
package 语句必须作为文件的第一个非注释语句出现。
现在,如果有人想使用MyClass,或者想使用mypackage 内的其他任何public 类,他们必须用import 关键字激活mypackage 内的名字,使它们能够使用。另一个办法则是指定完整的名称,import 关键字则可将其变得简洁得多。
5.1.1 创建独一无二的包名
根据约定,编译器强迫package 名的第一部分是类创建者的因特网域名。另一方面是将package 名解析成自己机器上的一个目录,也就是你的CLASSPATH。CLASSPATH 里能包含大量备用的搜索路径。然而,使用JAR 文件时要注意一个问题:必须将JAR文件的名字置于类路径里,而不仅仅是它所在的路径。
为导入的类首次创建一个对象时(或者访问一个类的static 成员时),编译器会在适当的目录里寻找同名的.class 文件(所以如果创建类X 的一个对象,就应该是X.class)。若只发现X.class,它就是必须使用的那一个类。然而,如果它在相同的目录中还发现了一个X.java,编译器就会比较两个文件的日期标记。如果X.java 比X.class 新,就会自动编译X.java,生成一个最新的X.class。
若通过*导入了两个库,而且它们包括相同的名字,编译器会报错,我们只需去掉一个类的导入,并指定这个类的完整路径。
5.1.2 自定义工具库
掌握前述的知识后,接下来就可以开始创建自己的工具库,以便减少或者完全消除重复的代码。所以从现在开始,无论什么时候只要做出了一个有用的新工具,就可将其加入tools 目录(或者自己的个人util 或tools 目录)。
请务必保证对于类路径的每个地方,每个名字都仅存在一个类。否则就会出现找不到方法的问题。
5.1.3 利用导入改变行为
5.1.4 包的停用
5.2 Java访问指示符
针对类内每个成员的每个定义,Java 访问指示符public,protected 以及private 都置于它们的最前面——无论它们是一个数据成员,还是一个方法。每个访问指示符都只控制着对那个特定定义的访问。
5.2.1 “友好的”
默认的访问没有关键
字,但它通常称为“友好”(Friendly )访问。这意味着当前包内的其他所有类都能访问“友好的”成员,但对包外的所有类来说,这些成员却是“私有”(Private)的,外界不得访问。由于一个编译单元(一个文件)只能从属于单个包,所以单个编译单元内的所有类相互间都是自动“友好”的。因此,我们也说友好元素拥有“包访问”权限。
友好访问允许我们将相关的类都组合到一个包里,使它们相互间方便地进行沟通。
5.2.2 public:接口访问
使用public 关键字时,它意味着紧随在public 后面的成员声明适用于所有人,特别是适用于使用库的客户程序员。
5.2.3 private:不能接触!
private 关键字意味着除非那个特定的类,而且从那个类的方法里,否则没有人能访问那个成员。
5.2.4 protected:“友好的一种”
若新建一个包,并从另一个包内的某个类里继承,则唯一能够访问的成员就是原来那个包的public 成员。当然,如果在相同的包里进行继承,那么继承获得的包能够访问所有“友好”的成员。有些时候,基础类的创建者喜欢提供一个特殊的成员,并允许访问衍生类。这正是protected 的工作。
5.3 接口与实现
我们通常认为访问控制是“隐藏实施细节”的一种方式。将数据和方法封装到类内后,可生成一种数据类型,它具有自己的特征与行为。但由于两方面重要的原因,访问为那个数据类型加上了自己的边界。第一个原因是规定客户程序员哪些能够使用,哪些不能。我们可在结构里构建自己的内部机制,不用担心客户程序员将其当作接口的一部分,从而自由地使用或者“滥用”。
这个原因直接导致了第二个原因:我们需要将接口同实施细节分离开。
为清楚起见,可考虑用特殊的样式创建一个类:将public 成员置于最开头,后面跟随protected、友好以及private 成员。这样做的好处是类的使用者可从上向下依次阅读,并首先看到对自己来说最重要的内容(即public 成员,因为它们可从文件的外部访问),并在遇到非公共成员后停止阅读,后者已经属于内部实施细节的一部分了。
5.4 类访问
在Java 中,亦可用访问指示符判断出一个库内的哪些类可由那个库的用户使用。若想一个类能由客户程序员调用,可在类主体的起始花括号前面某处放置一个public 关键字。它控制着客户程序员是否能够创建属于这个类的一个对象。
然而,我们同时还要注意到一些额外的限制:
(1) 每个编译单元(文件)都只能有一个public 类。每个编译单元有一个公共接口的概念是由那个公共类表达出来的。根据自己的需要,它可拥有任意多个提供支撑的“友好”类。但若在一个编译单元里使用了多个public 类,编译器就会向我们提示一条出错消息。
(2) public 类的名字必须与包含了编译单元的那个文件的名字完全相符,甚至包括它的大小写形式。所以对于Widget 来说,文件的名字必须是Widget.java,而不应是widget.java 或者WIDGET.java。同样地,如果出现不符,就会报告一个编译期错误。
(3) 可能(但并常见)有一个编译单元根本没有任何公共类。此时,可按自己的意愿任意指定文件名。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值