### 如果你把一个代码放到了某个位置,等过一会儿
回头再看时,有可能会发现有更好的方式去实现相同 的功
能。这正是重构的原动力之一,重构即重写代码, 以使
得它更可读、更容易理解,并因此更具有可维护性。
###面向对象设计中需要考虑的一个基本问题是:
“如何把变动的事物与保持不变的事物区分开来”
### Java 提供了访问权限修饰词,以供类库开发人员向
客户端程序员指明哪些是可用的,哪些是不可用的。 访问控
制权限等级,从最大权限到最小权限依次为: public 、
protected 、包访问权限(没有关键字)和 private 。
### 如何将构件捆绑到一个内聚的类库单元中,在java
中是使用关键字 package 加以控制。而访问权限修饰词 会因
类是存在于一个相同的包,还是存在于一个单独的包而 受到影
响。
》》包:库单元
### 包内包含有一组类,它们在单一的名字空间之下
被组织在了一起。
### 如果想导入某个包下的某个类或接口,可以使用
import 关键字
### 在 Java 中对名称空间完全控制并为每个类创建
唯一地标识符组合(非常重要)。
### 当编写一个 Java 源代码文件时,此文件通常被
称为编译单元(有时也称为转译单元)。每个编译单元
都必须有一个后缀名 .java ,而在编译单元内则可以有
一个 public 类,该类的名称必须与文件的名称相同(
包括大小写,但不包括文件的后缀名 .java) 。每个编译
单元只能有一个 public 类,否则编译器就不会接受。如果
在该编译单元之中还有额外的类的话,那么在包之外的世界
是无法看见这些类的,这是因为它们不是 public 类,而且
它们主要用来为 public 类提供支持。
---------代码组织
### 当编译一个 .java 文件时,在 .java 文件中的每个类都会
输出文件,而该输出文件的名称与 .java 文件中每个类的
的名称相同,只是多了一个后缀名 .class 。因此,在编译
少量的 .java 文件之后,会得到大量的 .class 文件。
### Java 可运行程序是一组可以打包并压缩为一个 Java
文档文件(JAR,使用Java 的jar 生成器)的 .class 文件。
Java 解释器负责这些文件的查找、装载和解释。
### 类库实际上是一组类文件。其中每个文件都有一个public
类,以及任意数量的非 public 类。因此每个文件都有一个构
件 。如果希望这些构件(每一个都有它们自己的独立的 .java
和 .class 文件)从属于同一个群组,就可以使用关键字
package
### 如果使用 package 语句,它必须是文件中除注释以外的
第一句程序代码。
### 注意,在Java 中包的命名规则全部使用小写字母,包括
中间的字母也是如此。
### 身为一名类库设计员,很有必要牢记:package 和 import
关键字允许你做的,是将单一的全局名字空间分割开,使得无
论多少人使用 Internet 以及 Java 开始编写类,都不会出现名称
冲突的问题。
---------创建独一无二的包名
###将特定包的所有 .class 文件都置于一个文件目录下
### 如果你打算发布你的 Java 程序代码,取得一个域名,是很有
必要的。
(因为一般在设定包名的时候,通常是将域名反过来写,并/
且 是小写)
### Java 解释器的运行过程如下:首先,找出环境变量 CLASSPATH
(可以通过操作系统来设置,有时也可以通过安装程序--用来在你的
机器上安装 Java 或基于 Java 工具--来设置)。CLASSPATH 包含
一个或多个目录,用作查找 .class 文件的根目录。从根目录开始,
解释器获取包的名称并将每个包点替换成反斜杠,以从 CLASSPATH
根中产生路径名称(于是,package foo.bar.baz 就变成为
foo\bar\baz 或 foo/bar/baz 或其他,这一切取决于操作系统)。得到
的路径会与 CLASSPATH 中的各个不同的项相连接,解释器就在这些
目录中查找与你所要创建的类名称相关的 .class 文件(解释器还会去
查找某些涉及 Java 解释器所在位置的标准目录)。
### 在使用 JAR 文件时会有一些变换。必须在类路径中将 JAR 文件的
实际名称写清楚,而不仅是指明它所在位置的目录。
例如:
CLASSPATH = . ; D:\diannaoruanjian\jdk\lib\tools.jar
说明:上面的类路径中,开始是一个英文的点(.)表示的是当前路径
### 冲突:
在java 类库中,可能存在同样的类名称但是它们在不同的包下
@@@ 可以使用单个类导入的形式来防止冲突,只要你在同一个程序
中没有使用有冲突的名字
@@@ 在使用了有冲突名字的情况下,必须返回到指定全名的方式。
---------定制工具库
---------用 import 改变行为
### Java 中没有 C 语言的条件编译功能。Java 中去掉此功能的原因可
能是因为 C 语言在绝大多数情况下是用此功能来解决跨平台问题的,
即程序的不同部分是根据不同的平台来编译的。由于 Java 自身可以
自动跨越不同的平台,因此这个功能对 Java 而言是没有必要的。
### 条件编译还有其他一些有价值的用途。调试就是一个很常见的
用途。调试功能在开发过程中是开启的,而在发布过程中是禁用的。
可以通过修改被导入的 package 的方法来实现这一目的,修改的方法
是将你程序中用到的代码从调试版改为发布版。这一技术可以适用于
任何种类的条件代码。
---------对使用包的忠告
### 务必记住,无论何时创建包,都已经在给定包的名称的时候隐藏地
指定了目录结构。这个包必须位于其名称所指定的目录之中,而该目录
必须是在以 CLASSPATH 开始的目录中可以查询到的。
### 注意,编译过的代码通常放置在与源代码的不同目录中,但是必须
保证 JVM 使用 CLASSPATH 可以找到该路径
》》Java 访问权限修饰词
### public 、protected 和 private 这几个 Java 访问权限修饰词在使用时,
是置于类中每个成员的定义之前的---无论它是一个域还是一个方法。每个
访问权限修饰词仅控制它所修饰的特定定义的访问权。
---------包访问权限
### 默认访问权限没有任何关键字,但通常是指包访问权限。
###由于一个编译单元(即一个文件),只能隶属于一个包,所以经由包
访问权限,处于同一个编译单元中所有类彼此之间都是自动可访问的。
###包访问权限允许将包内所有相关的类组合起来,以使它们彼此之间可
以轻松地相互作用。当把类组织起来放进一个包内之时,也就给它们
的访问权限的成员赋予了相互访问的权限,你“拥有”了该包内的程序
代码。
### 取得对某成员的访问权的唯一途径是:
1. 使该成员成为 public 。于是,无论是谁,无论在哪里,都可以访问
该成员。
2.通过不加访问权限修饰词并将其他类放置于同一个包内的方式给
成员赋予包访问权。于是包内的其他类也就可以访问该成员了。
3.继承技术。继承而来的类既可以访问 public 成员也可以访问
protected 成员(但访问 private 成员却不行)。只有两个类都处于
同一个包内时,它才可以访问包访问权限的成员。
4.提供访问器(accessor)和变异器(mutator)方法(也称get/set
方法),以读取和改变数值。对OOP 而言,这是最优雅的方式,而且
这也是 JavaBeans 的基本原理。
---------public :接口访问权限
### 不要错误地认为 Java 总是将当前目录视作是查找行为的起点之一。
如果你的 CLASSPATH 之中缺少了一个“.”作为路径之一的话,Java
就不会查找那里。
### 默认包:
给处于相同目录并且没有给自己设定任何包名称的Java 文件,看作是
隶属于该目录的默认包之中,于是它们为该目录中所有其他的文件都
提供了包访问权限。
---------private :你无法访问
### private 的意思是,除了包含该成员的类之外,其他任何类都无法访问
这个成员。
### 默认的包访问权限通常已经提供了充足的隐藏措施。请记住,使用类的
客户端程序员是无法访问包访问权限的成员的。这样做很好,因为默认
访问权限是一种我们常用的权限,同时也是一种在忘记添加任何访问权限
控制时能够自动得到的权限。
### private 的使用是非常重要的,尤其是在多线程环境下。
### 任何可以肯定只是该类的一个“助手”方法的方法,都可以把它指定为
private ,以确保不会在包内的其他地方误用到它,于是也防止了你会
改变或删除这个方法。将方法指定为 private 确保了你拥有这种选择权。
### 除非必须公开底层实现细目(此种境况很少见),否则就应该将所有
的域指定为 private 。然而,不能因为在类中某个对象的引用是 private ,
就认为其他的对象无法拥有该对象的 public 引用。
---------protected :继承访问权限
### 为了从现有的类中继承,需要声明新类 extends (扩展)了一个现有
的类,如下:
class Foo extends Bar {
}
###有时, 基类的创建者会希望有某个特定成员,把对它的访问权限赋予
派生类而不是所有类。这就需要 protected 来完成这一工作。protected
也提供了包访问权限,也就是说,相同包内的其他类可以访问 protected
元素。
### 如果类 Cookie 中存在一个方法 bite() 的话,那么该方法同时也存在于
任何一个从 Cookie 继承而来的类中。如果该 bite() 方法有包访问权限
而且它位于另一个包内,所有我们在子类的中无法使用 bite() 方法的。
如果将上面的 bite() 方法的权限改为 protected 的话,在子类中就
可以访问父类中的 bite() 方法了。其实 protected 的权限要比包访问
权限要大。(将bite() 方法的权限增大了)
》》接口和实现
### 访问权限的控制常被称为是具体实现的隐藏。把数据和方法包装进
类中,以及具体实现的隐藏,常共同被称作是封装。其结果是一个同时
带有特征和行为的数据类型。
### 访问权限控制将权限的边界划在了数据类型的内部。有两个原因:
第一:
要设定客户端程序员可以使用和不可以使用的界限。可以在结构中
建立自己的内部机制,而不必担心客户端程序员会偶然地将内部机制
当作是他们可以使用的接口的一部分。
第二:
将接口和具体实现进行分离
### 将接口展现给某个类的使用者实际上是类浏览器的任务。类浏览器是
一种以非常有用的方式来查阅所有可用的类,并告诉你用它们可以做些
什么(也就是显示出可用成员)的工具。在 Java 中,用Web 浏览器
JDK 文档可以得到使用类浏览器的相同效果。
》》类的访问权限
### 为了控制某个类的访问权限,修饰词必须出现于关键字 class 之前。
例如:
public class Widget {
}
### 除了上面的内容,还有一些额外的限制:
1. 每个编译单元(文件)都只能有一个 public 类。
2. public 类的名称必须完全与该编译单元的文件名匹配,包括
大小写。
3. 虽然不是很常用,但编译单元内完全不带 public 类也是可能的。
在这种情况下,可以随意对文件命名。
### 类既不可以是 private 的,也不可以是 protected 的。所以对于类的
访问权限,仅有两个选择:包访问权限或public 。如果不希望其他
任何人对该类拥有访问权限,可以把所有的构造器都指定为 private ,
从而阻止任何人创建该类的对象,但是有一个例外,就是你在该
类的 static 成员内部可以创建。下面是一个示例:
class Soup1 {
private Soup1() {
}
public static Soup1 makeSoup(){
return new Soup1();
}
}
### 请一定要牢记,如果没有明确地至少创建一个构造器的话,就会帮你
创建一个默认构造器(不带有任何参数的构造器)。如果我们自己编
写了默认的构造器,那么就不会自动创建它了。
### 如果没能为类访问权限指定一个访问修饰符,它就会默认得到包访问
权限。这就意味着该类的对象可以由包内任何其他类来创建,但是在包
外则是不行的(一定要记住,相同目录下的所有不具有明确 package
声明的文件,都被视为该目录下默认包的一部分。)然而,如果该类的
某个 static 成员是 public 的话,则客户端程序员仍旧可以调用该 static
成员,尽管他们并不能生成该类的对象。
》》总结
### 对于 Java ,关键字 package 、包的命名模式和关键字 import ,可以使
你对名称进行完全的控制,因此名称冲突的问题是容易避免的。
### 控制对成员的访问权限有两个原因:
第一:
为了使用户不要触碰那些他们不该碰触的部分,这些部分对于
类内部的操作是必要的,但是它并不属于客户端程序员所需接口的一
部分。因此,将方法和域指定成 private ,对客户端程序员而言是一种
服务。
第二:(也是最重要的)
为了让类库设计者可以更改类的内部工作方式,而不必担心这样
会对客户端程序员产生重大的影响。
### 注意,访问权限控制专注于类库创建者和该类库的外部使用者之间的关系,
这种关系也是一种通信方式。