JAVA编程思想学习 --- 第五章 (隐藏实施过程)

来源:互联网 发布:免费企业名录软件 编辑:程序博客网 时间:2024/05/29 14:27
 进行面向对象的设计时,一项基本的考虑是:如何将发生变化的东西与保持不变的东西分隔开。”


1.包:库单元
     我们用 import 关键字导入一个完整的库时,就会获得“包”( Package)。例如:
     import java.util.*;
     它的作用是导入完整的实用工具( Utility)库,若想导入单独一个类,可在 import 语句里指定那个类的名字:
     import java.util.Vector;
     之所以要进行这样的导入,是为了提供一种特殊的机制,以便管理“命名空间”( Name Space)。我们所有 类成员的名字相互间都会隔离起来。位于类 A 内的一个方法 f()不会与位于类 B 内的、拥有相同“签名” (自变量列表)的 f()发生冲突。
     为 Java 创建一个源码文件的时候,它通常叫作一个“编辑单元”(有时也叫作“翻译单元”)。每个编译单 元都必须有一个以.java 结尾的名字。而且在编译单元的内部,可以有一个公共( public)类,它必须拥有 与文件相同的名字(包括大小写形式,但排除.java 文件扩展名)。如果不这样做,编译器就会报告出错。 每个编译单元内都只能有一个 public 类(同样地,否则编译器会报告出错)。那个编译单元剩下的类(如果 有的话)可在那个包外面的世界面前隐藏起来,因为它们并非“公共”的(非public),而且它们由用于主 public 类的“支撑”类组成。

2.package的作用 
     若在一个文件的开头使用下述代码:
     package mypackage;
     那么 package 语句必须作为文件的第一个非注释语句出现该语句的作用是指出这个编译单元属于名为 mypackage 的一个库的一部分。或者换句话说,它表明这个编译单元内的 public 类名位于 mypackage 这个名 字的下面。如果其他人想使用这个名字,要么指出完整的名字,要么与mypackage 联合使用 import 关键字 (使用前面给出的选项)。注意根据 Java 包(封装)的约定,名字内的所有字母都应小写,甚至那些中间单
词亦要如此。例如,假定文件名是 MyClass.java。它意味着在那个文件有一个、而且只能有一个 public 类。而且那个类 的名字必须是 MyClass(包括大小写形式):


3.解释器的工作程序与包名的创建
     Java 解释器的工作程序如下:首先,它找到环境变量CLASSPATH(将 Java 或者具有 Java 解释能力的工具— — 如浏览器—— 安装到机器中时,通过操作系统进行设定)。CLASSPATH 包含了一个或多个目录,它们作为 一种特殊的“根”使用,从这里展开对.class 文件的搜索。从那个根开始,解释器会寻找包名,并将每个点 号(句点)替换成一个斜杠,从而生成从 CLASSPATH 根开始的一个路径名(所以 package foo.bar.baz 会变 成 foo\bar\baz 或者 foo/bar/baz;具体是正斜杠还是反斜杠由操作系统决定)。随后将它们连接到一起, 成为 CLASSPATH 内的各个条目(入口)。以后搜索.class 文件时,就可从这些地方开始查找与准备创建的类 名对应的名字。此外,它也会搜索一些标准目录—— 这些目录与 Java 解释器驻留的地方有关。
     为进一步理解这个问题,下面以我自己的域名为例,它是 bruceeckel.com。将其反转过来后, com.bruceeckel 就为我的类创建了独一无二的全局名称( com, edu, org, net 等扩展名以前在 Java 包中都 是大写的,但自 Java 1.2 以来,这种情况已发生了变化。现在整个包名都是小写的)。由于决定创建一个名 为 util 的库,我可以进一步地分割它,所以最后得到的包名如下:
     package com.bruceeckel.util;
     现在,可将这个包名作为下述两个文件的“命名空间”使用:


4.自动编译
     为导入的类首次创建一个对象时(或者访问一个类的static 成员时),编译器会在适当的目录里寻找同名 的.class 文件(所以如果创建类 X 的一个对象,就应该是 X.class)。若只发现 X.class,它就是必须使用 的那一个类。然而,如果它在相同的目录中还发现了一个 X.java,编译器就会比较两个文件的日期标记。如 果 X.java 比 X.class 新,就会自动编译 X.java,生成一个最新的 X.class。 对于一个特定的类,或在与它同名的.java 文件中没有找到它,就会对那个类采取上述的处理。


5.冲突
     若通过*导入了两个库,而且它们包括相同的名字,这时会出现什么情况呢?例如,假定一个程序使用了下述
导入语句:
     import com.bruceeckel.util.*;
     import java.util.*;
     由于 java.util.*也包含了一个 Vector 类,所以这会造成潜在的冲突。然而,只要冲突并不真的发生,那么 就不会产生任何问题—— 这当然是最理想的情况,因为否则的话,就需要进行大量编程工作,防范那些可能 可能永远也不会发生的冲突。
     如现在试着生成一个 Vector,就肯定会发生冲突。如下所示:
     Vector v = new Vector();
     它引用的到底是哪个 Vector 类呢?编译器对这个问题没有答案,读者也不可能知道。所以编译器会报告一个 错误,强迫我们进行明确的说明。例如,假设我想使用标准的 Java Vector,那么必须象下面这样编程:
     java.util.Vector v = new java.util.Vector();
     由于它(与 CLASSPATH 一起)完整指定了那个 Vector 的位置,所以不再需要 import java.util.*语句,除 非还想使用来自 java.util 的其他东西。


6.Java访问指示符
     针对类内每个成员的每个定义, Java 访问指示符poublicprotected 以及private 都置于它们的最前面— — 无论它们是一个数据成员,还是一个方法。每个访问指示符都只控制着对那个特定定义的访问。
     如果根本不指定访问指示符,就象本章之前的所有例子那样,这时会出现什么情况呢?默认的访问没有关键 字,但它通常称为“友好”( Friendly )访问。这意味着当前包内的其他所有类都能访问“友好的”成员, 但对包外的所有类来说,这些成员却是“私有”( Private)的,外界不得访问。由于一个编译单元(一个文 件)只能从属于单个包,所以单个编译单元内的所有类相互间都是自动“友好”的。因此,我们也说友好元 素拥有“包访问”权限
     为获得对一个类的成员的访问权限,唯一的方法就是:
     (1) 使成员成为“ public”(公共的)。这样所有人从任何地方都可以访问它。
     (2) 变成一个“友好”成员,方法是舍弃所有访问指示符,并将其类置于相同的包内。这样一来,其他类就 可以访问成员。
     (3) 正如以后引入“继承”概念后大家会知道的那样,一个继承的类既可以访问一个 protected 成员,也可 以访问一个 public 成员(但不可访问 private 成员)。只有在两个类位于相同的包内时,它才可以访问友好 成员。但现在不必关心这方面的问题。
     (4) 提供“访问器/变化器”方法(亦称为“获取/设置”方法),以便读取和修改值。这是OOP 环境中最 正规的一种方法,也是 Java Beans 的基础.



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

8.private : 不能接触
     private 关键字意味着除非那个特定的类,而且从那个类的方法里,否则没有人能访问那个成员。同一个包 内的其他成员不能访问 private 成员,这使其显得似乎将类与我们自己都隔离起来。另一方面,也不能由几 个合作的人创建一个包。
     如果构建器的属性是 private,所以可防止 对这个类的继承


9.protected : 友好的一种
     protected 关键字为我们引入了一种名为“继承”的概念,它以现有的类为基础,并在其中加入新的成员, 同时不会对现有的类产生影响—— 我们将这种现有的类称为“基础类”或者“基本类”( Base Class)。亦 可改变那个类现有成员的行为。对于从一个现有类的继承,我们说自己的新类“扩展”( extends)了那个现 有的类。
     若新建一个包,并从另一个包内的某个类里继承,则唯一能够访问的成员就是原来那个包的 public 成员。当 然,如果在相同的包里进行继承,那么继承获得的包能够访问所有“友好”的成员。有些时候,基础类的创 建者喜欢提供一个特殊的成员,并允许访问衍生类。这正是protected 的工作。



10.接口与实现 
     我们通常认为访问控制是“隐藏实施细节”的一种方式。将数据和方法封装到类内后,可生成一种数据类 型,它具有自己的特征与行为。但由于两方面重要的原因,访问为那个数据类型加上了自己的边界。
     第一个 原因是规定客户程序员哪些能够使用,哪些不能。我们可在结构里构建自己的内部机制,不用担心客户程序 员将其当作接口的一部分,从而自由地使用或者“滥用”。
     第二个原因:我们需要将接口同实施细节分离开。若结构在一系列程序中使用,但用户 除了将消息发给 public 接口之外,不能做其他任何事情,我们就可以改变不属于 public 的所有东西(如 “友好的”、 protected 以及 private),同时不要求用户对他们的代码作任何修改



11.类访问
     (1) 每个编译单元(文件)都只能有一个 public 类。每个编译单元有一个公共接口的概念是由那个公共类表 达出来的。根据自己的需要,它可拥有任意多个提供支撑的“友好”类。但若在一个编译单元里使用了多个 public 类,编译器就会向我们提示一条出错消息。
     (2) public 类的名字必须与包含了编译单元的那个文件的名字完全相符,甚至包括它的大小写形式。所以对 于 Widget 来说,文件的名字必须是 Widget.java,而不应是 widget.java 或者 WIDGET.java。同样地,如果 出现不符,就会报告一个编译期错误。
     (3) 可能(但并常见)有一个编译单元根本没有任何公共类。此时,可按自己的意愿任意指定文件名




最近在看JAVA编程思想(第四版)这本书,将书中的一些知识点容易遇到或者混淆的概念记录下来,只是作为备忘,希望也能帮到需要的人,特此申明.
原创粉丝点击