Java笔记整理:复用类


复用代码最简单的方式就是复制代码
可以通过创建新类进行复用:

  1. 在新类中产生现有类的对象(组合)
  2. 按照现有类来创建新类(继承)

组合

每一个非基本类型的类都有一个toString方法
类中基本类型的域会自动初始化为0,对象引用初始化为null
null引用可以被打印

初始化引用的方式:

  1. 定义的地方。这将会在构造器之前执行
  2. 构造器中
  3. 正要使用之前。也叫惰性初始化
  4. 使用实例初始化

继承

创建一个类时,总是在继承。除非显式指出继承某类,否则将隐式继承Object类
继承将自动获得基类的所有域和方法
使用super关键字调用基类版本的域或方法

初始化基类

创建一个导出类的对象时,该对象会包含一个基类的子对象
导出类的构造器中自动先调用基类的构造器
构造过程是从基类向外扩散的,即先调用基类的,再调用导出类的。这使得基类内容在导出类可以访问它时,就已经完成了初始化

Java会调用的是基类的默认构造器,如果基类没有,需要用super显式地调用基类的带参构造器
调用基类构造器必须是导出类构造器中的第一件事


代理

代理是一个编程模式,是继承和组合的中庸之道

将成员对象置于类中(组合),在类中暴露成员对象的所有方法(类似继承),相当于新类代理了各个成员对象的行为


结合使用组合和继承

确保正确清理

由于不知道垃圾回收器何时回收,因此需要显式地遍写方法来进行收尾
可以使用try-finally代码块。无论try是如何退出的,finally块总会被执行

清理顺序应和构造顺序相反

不要使用finalize

名称屏蔽

在导出类中对基类的方法进行重载,不会屏蔽基类的所有重载版本
@Override注解可以防止在不想重载时意外进行了重载


选择组合或继承

组合和继承都是在新类中放置子对象,组合是显式的,继承是隐式的
组合通常是希望在新类中使用现有类的功能,而并非得到其接口。用户看到的只有新类的接口,而看不到成员的接口
继承是希望使用现有类,开发它的特殊版本

  • 组合 = has-a
  • 继承 = is-a

protected

继承使protected关键字具有意义
应尽量使用private,然后用protected限制继承者的访问权限


向上转型

称为向上转型是因为,类层次关系中基类是上层的
向上转型总是安全的
向上转型会丢失信息
向上转型的过程中,类接口只会丢失方法,而不会获取方法

继承应当慎用,使用继承前应考虑是否需要进行向上转型


final关键字

final数据

final的作用是向编译器通知一块数据是恒定不变的

  1. 永不改变的编译时常量
  2. 运行时初始化的值,希望不被改变

JAVA会对final使用优化进行优化,对于域会在编译时计算表达式,对于方法会使用内嵌机制
编译时常量必须是基本类型,定义该常量时必须对其进行赋值

final修饰对象引用时,表示该引用恒定不变。一旦该引用指向一个对象,就不能指向别的对象

JAVA编写规范中,既是static又是final的域命名用大写,用下划线分隔单词

空白final

声明为final但没有给定初值的域
无论如何,必须在域的定义处或每个构造器中对final进行赋值,否则将会在使用该域时产生异常

final参数

表示无法在方法中更改参数的值或指向的对象

final方法

使用final方法的原因:

  1. 锁定方法,防止导出类修改其含义
  2. 效率。使用内嵌调用提高效率

类中的private方法都隐式地指定为final
覆盖一个private方法不会导致错误,但不会覆盖,而是产生了一个新方法

final类

表示无法被继承
类中的所有方法都隐式指定为final


初始化以及类的加载

编译代码文件只有在需要使用时才会被加载
加载发生于创建类的第一个对象或者访问静态域或方法时
所有的静态域和代码段都会在加载时,按照书写顺序依次初始化

在使用导出类时,会加载基类
对于静态成员,会先初始化基类的