07、第八章复用

组合语法

初始化引用有四种方法:

1、 当对象被定义时这意味着它们总是在调用构造函数之前初始化;
2、 在该类的构造函数中;
3、 在实际使用对象之前这通常称为延迟初始化在对象创建开销大且不需要每次都创建对象的情况下,它可以减少开销;
4、 使用实例初始化;

继承语法

初始化基类

Java 自动在派生类构造函数中插入对基类构造函数的调用。

构造从基类“向外”进行,因此基类在派生类构造函数能够访问它之前进行初始化。即使不为 Cartoon 创建构造函数,编译器也会为你合成一个无参数构造函数,调用基类构造函数。

先调用基类构造器,从最基类向外层层调用。

带参数的构造函数

对基类构造函数的调用必须是派生类构造函数中的第一个操作。

委托

Java不直接支持的第三种重用关系称为委托。这介于继承和组合之间,因为你将一个成员对象放在正在构建的类中(比如组合),但同时又在新类中公开来自成员对象的所有方法(比如继承)。

结合组合与继承

保证适当的清理

在清理方法 中,还必须注意基类和成员对象清理方法的调用顺序,以防一个子对象依赖于另一个子对象。首先,按与创建的相反顺序执行特定于类的所有清理工作。(一般来说,这要求基类元素仍然是可访问的。) 然后调用基类清理方法。

组合与继承的选择

当你想在新类中包含一个已有类的功能时,使用组合,而非继承。

当使用继承时,使用一个现有类并开发出它的新版本。通常这意味着使用一个通用类,并为了某个特殊需求将其特殊化。

是一个”的关系是用继承来表达的,而“有一个“的关系则用组合来表达。

protected

protected 也提供了包访问权限。

向上转型

继承图中派生类转型为基类是向上的,所以通常称作向上转型。因为是从一个更具体的类转化为一个更一般的类,所以向上转型永远是安全的。

再论组合和继承

尽量少使用继承。

使用继承前,问一问“我需要向上转型吗?”

final关键字

final 数据

在Java 中,编译时常量必须是基本类型,而且用关键字 final 修饰。

对于基本类型,final 使数值恒定不变,而对于对象引用,final 使引用恒定不变。一旦引用被初始化指向了某个对象,它就不能改为指向其他对象。但是,对象本身是可以修改的,Java 没有提供将任意对象设为常量的方法。这一限制同样适用数组,数组也是对象。

不能因为某数据被 final 修饰就认为在编译时可以知道它的值。可以当值在运行时被初始化。

空白 final

必须在定义时或在每个构造器中执行 final 变量的赋值操作。这保证了 final 属性在使用前已经被初始化过。

final 参数

在参数列表中,将参数声明为 final 意味着在方法中不能改变参数指向的对象或基本变量。这个特性主要用于传递数据给匿名内部类。

final 方法

使用final 方法的原因是:给方法上锁,防止子类通过覆写改变方法的行为。

final 和 private

如果一个方法是 private 的,它就不是基类接口的一部分。

但是如果你在派生类中以相同的命名创建了 public,protected 或包访问权限的方法,这些方法与基类中的方法没有联系,你没有覆写方法,只是在创建新的方法而已。由于 private 方法无法触及且能有效隐藏,除了把它看作类中的一部分,其他任何事物都不需要考虑到它。

final 类

final 类不能被继承。

类初始化和加载

构造器也是一个 static 方法尽管它的 static 关键字是隐式的。

类初始化顺序:

1、 加载基类不论是否创建了基类的对象,基类都会被加载;
2、 根基类的static的初始化开始执行,接着是派生类,以此类推;
3、 创建对象首先,对象中的所有基本类型变量都被置为默认值,对象引用被设为null——这是通过将对象内存设为二进制零值一举生成的接着会调用基类的构造器基类构造器和派生类构造器一样以相同的顺序经历相同的过程当基类构造器完成后,实例变量按文本顺序初始化最终,构造器的剩余部分被执行;

当开始设计一个系统时,记住程序开发是一个增量过程,正如人类学习。它依赖实验,你可以尽可能多做分析,然而在项目开始时仍然无法知道所有的答案。如果把项目视作一个有机的,进化着的生命去培养,而不是视为像摩天大楼一样快速见效,就能获得更多的成功和更迅速的反馈。继承和组合正是可以让你执行如此实验的面向对象编程中最基本的两个工具。