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

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

  • Base 类:

    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 类:

    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 方法

    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);
    }
    

答:

  • 输出结果如下:

    ---- 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. 一个类的信息包括哪些部分?

答:

  • 类变量(静态变量)
  • 类初始化代码
  • 类方法(静态方法)
  • 实例变量
  • 实例初始化代码
  • 实例方法
  • 父类信息引用

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

答:

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

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

答:

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

6. 类加载过程是怎样的?

答:

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

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

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

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

答:

  • 过程:

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

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

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

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

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

答:

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

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

答:对。

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

答:通过对象访问类变量,系统会转换为类名直接访问静态变量

-------------本文结束感谢您的阅读-------------