0%

Java 类的继承(三):继承实现的基本原理

1. 请写出下面代码的输出结果

  • Base

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    public class Base {
    public static int s;
    private int a;

    static {
    System.out.println("基类静态代码块,s: " + s);
    s = 1;
    }

    {
    System.out.println("基类实例代码块,a: " + a);
    a = 1;
    }

    public Base() {
    System.out.println("基类构造方法,a: " + a);
    a = 2;
    }

    protected void step() {
    System.out.println("base s: " + s + ", a: " + a);
    }

    public void action() {
    System.out.println("start");
    step();
    System.out.println("end");
    }
    }
  • Child

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    public class Child extends Base {
    public static int s;
    private int a;

    static {
    System.out.println("子类静态代码块,s: " + s);
    s = 10;
    }

    {
    System.out.println("子类实例代码块,a: " + a);
    a = 10;
    }

    public Child() {
    System.out.println("子类构造方法,a: " + a);
    a = 20;
    }

    protected void step() {
    System.out.println("child s: " + s + ", a: " + a);
    }
    }
  • main() 方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public static void main(String[] args) {
    System.out.println("---- new Child()");
    Child c = new Child();
    System.out.println("\n---- c.action()");
    c.action();
    Base b = c;
    System.out.println("\n---- b.action()");
    b.action();
    System.out.println("\n---- b.s " + b.s);
    System.out.println("\n---- c.s: " + c.s);
    }
  • 输出结果如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    ---- new Child()
    基类静态代码块,s: 0
    子类静态代码块,s: 0
    基类实例代码块,a: 0
    基类构造方法,a: 1
    子类实例代码块,a: 0
    子类构造方法, a: 10

    ---- c.action()
    start
    child s: 10, a: 20
    end

    ---- b.action()
    start
    child s: 10, a: 20
    end

    ---- b.s: 1
    ---- c.s: 10
  • 总结:基静态、子静态 -> 基实例代码块、基构造 -> 子实例代码块、子构造

2. 类的加载什么意思,怎么理解这个概念

  • 类的加载是指将类的相关信息加载进内存
  • 在 Java 中,类是动态加载的,当第一次使用这个类的时候才会加载
  • 加载一个类时,会查看其父类是否已加载,如果没有,则会先加载其父类

3. 一个类的信息包括哪些部分

  1. 类变量(静态变量)
  2. 类初始化代码
  3. 类方法(静态方法)
  4. 实例变量
  5. 实例初始化代码
  6. 实例方法
  7. 父类信息引用

4. 类初始化代码包括哪些部分

  • 定义静态变量时的赋值语句
  • 静态初始化代码块

5. 实例初始化代码包括哪些部分

  • 定义实例变量时的赋值语句
  • 实例初始化代码块
  • 构造方法

6. 类加载过程是怎样的

  • 分配内存保存类的信息
  • 给类变量赋默认值
  • 加载父类
  • 设置父子关系
  • 执行类初始化代码

7. 怎样理解方法区这个概念

  • 存放类的信息的一个内存区Object 类肯定会存在于方法区

8. 创建对象的过程是怎样的

  • 过程

    • 分配内存
    • 对所有实例变量赋默认值
    • 执行实例初始化代码
  • 注意

    • 分配的内存包括本类和所有父类的实例变量,但不包括任何静态变量
    • 实例初始化代码的执行从父类开始,再执行子类的。但在任何类执行初始化代码之前,所有实例变量都已设置完默认值
    • 每个对象除了保存类的实例变量之外,还保存着实际类信息的引用

9. 动态绑定机制中方法的调用过程是怎样的

  • 动态绑定实现的机制就是根据对象的实际类型查找要执行的方法
  • 子类型中找不到的时候再查找父类

10. 虚方法表的含义及作用

  • 含义在类加载的时候为每个类创建一个表,这个表叫做虚方法表,这个表记录该类的对象所有动态绑定的方法(包括父类的方法)及其地址,但一个方法只有一条记录,子类重写了父类方法后只会保留子类的
  • 作用优化方法调用的效率。如果继承的层次比较深,要调用的方法位于比较上层的父类,如果不用虚方法表的话则调用的效率是比较低的,因为每次调用都要进行很多次查找。使用虚方法表的话,当通过对象动态绑定方法的时候,只需要查找这个表就可以了,不需要挨个查找每个父类

11. 对变量的访问是静态绑定的,这句话对吗

12. 对象访问类变量(静态变量)的实现机制是

  • 通过对象访问类变量,系统会转换为类名直接访问静态变量
  • 所以,在很多编程规范里建议直接使用类名访问静态变量
-------------------- 本文结束感谢您的阅读 --------------------