1、复用类的方法

类包含两种方法:组合和继承

1.组合

新的类中定义已有类的对象。

  1. class ClassA{
  2. }
  3. class ClassB{
  4. private ClassA a = new ClassA();
  5. }

2.继承

新的类继承已有类的所有内容并增加新的内容。使用关键词extends

  1. class ClassA{
  2. int value1;
  3. public void setValue1(int value1){
  4. this.value1 = value1;
  5. }
  6. }
  7. class ClassB extends ClassA{
  8. public void f(){
  9. setValue1(2);
  10. }
  11. }

(1)初始化
子类初始化方法会默认把父类的初始化方法放在自身初始化方法的前面执行(详见第6节类加载)。若父类的构造器有参数,则在子类构造方法里使用super关键字显示调用父类构造器。

3.代理

直接继承有时候会造成把父类的方法名泄露,此时如果要修改父类代码,调用子类的代码均需要修改。此时我们使用代理。

  1. public class ClassA{
  2. public void f(){}
  3. }
  4. public class ClassB{
  5. ClassA ca = new ClassA();
  6. public void f(){
  7. ca.f();
  8. }
  9. }

代理类不继承父类,而是组合父类对象,并创建一个同名方法名,在方法内调用父类对象中的同名方法。

2、使用复用类方法注意事项

(1)正确清理
父类显式设置销毁方法,每个子类重写该方法。采用try-finally关键字,显式的在finally里设置销毁方法,确保try中代码无论是否执行,都会稳定运行finally里的销毁方法。
(2)名称屏蔽
重写方法前面加@override,防止不想被重载的时候错误重载。

  1. @override void f(){
  2. }

3、选择复用类方法

(1)组合:想在新类中使用已有类的功能可以直接选组合。嵌入已有类的private对象,实现所需功能。使用者只需要关系已有类提供的public方法的功能即可。
(2)继承:在已有类的基础上开发一个特殊定制版本的新类。为其他服务提供接口。

4、向上转型

由子类向父类转型,在继承图上是向上移动的,因此叫做向上转型。
从较为专业的类型转换成较为通用的类型。这是一个安全的过程,这个过程中只存在丢失子类特有成员和方法的情况,对于父类的成员和方法并不影响。

5、final

(1)数据

  • 编译时常量

    1. private static final int i1 = 9;
    2. private final int i2 = 6;
  • 运行时初始化常量或对象

    1. private static final int i1 = Random.nextInt(20);
    2. static final int i2 = Random.nextInt(20);
    3. private final Value i3 = new Value(20);//对象

    对于对象,不变的是引用,内容可以改变。

  • 空白final

如果final变量或对象定义时没有初始化,这些变量和对象默认为初值或null,之后必须在构造器中进行初始化。防止报错。

  • 参数final

方法中参数设置为final,保证基本类型的参数无法修改内容,对象的参数无法修改引用。
(2)方法
final方法在子类中无法重写。
编译器对final方法的调用全部改成内嵌代码。会带来两种影响:

  1. 1)代码较小,这样会提高运行效率,
  2. 减少正常程序执行过程中压栈和出栈的操作
  3. 2)代码较大,反而使得内嵌代码过多,程序过大。

因此对方法是否final需要谨慎。
(3)类
不允许继承该类。

6、初始化及类加载

  1. 运行文件ClassA.class时,第一时间会试图访问其中的main()方法
  2. 加载器开始启动找出,ClassA类的编译代码,然后根据extends发现有个父类,先加载父类,如果还有父类就继续向上加载至根父类。
  3. 然后开始从根父类开始向下static初始化。
  4. 创建对象,默认引用为null,
  5. 从根父类开始执行构造器,将实例变量初始化。