一、代码展示

  1. public class Father {
  2. private int i = test();
  3. private static int j = method();
  4. static {
  5. System.out.print("(1)");
  6. }
  7. Father() {
  8. System.out.print("(2)");
  9. }
  10. {
  11. System.out.print("(3)");
  12. }
  13. public int test() {
  14. System.out.print("(4)");
  15. return 1;
  16. }
  17. public static int method() {
  18. System.out.print("(5)");
  19. return 1;
  20. }
  21. }
  1. public class Son extends Father{
  2. private int i = test();
  3. private static int j = method();
  4. static {
  5. System.out.print("(6)");
  6. }
  7. Son() {
  8. System.out.print("(7)");
  9. }
  10. {
  11. System.out.print("(8)");
  12. }
  13. @Override
  14. public int test() {
  15. System.out.print("(9)");
  16. return 1;
  17. }
  18. public static int method() {
  19. System.out.print("(10)");
  20. return 1;
  21. }
  22. public static void main(String[] args) {
  23. Son s1 = new Son();
  24. System.out.println();
  25. Son s2 = new Son();
  26. }
  27. }

输出结果?为什么是这样子的。

  1. (5)(1)(10)(6)(9)(3)(2)(9)(8)(7)
  2. (9)(3)(2)(9)(8)(7)

调用顺序

main方法->父类被调用的静态方法->父类的静态代码块->子类被调用的静态方法->子类的静态代码块—>子类被调用的非静态方法—>父类的非静态代码块—>父类构造方法—>父类中被子类重写的方法(在这里就是指父类中的 int i = test();)—>子类的非静态代码块—>子类的构造方法

为什么(9)出现了两次?

因为非静态方法前面其实有一个默认的对象this,this在构造器(或)它表示的是正在创建的对象,因为此时是子类的test()运行,这里父类的i=test() 执行的是子类重写的test()方法

为什么第二次执行少了几个步骤

因为(5)(1)(10)(6)是静态方法,只会执行一次

二、类的初始化过程

  • 一个类要创建实例需要先加载并初始化该类
    • main方法所在的类需要先加载和初始化
  • 一个子类要初始化的时候需要先初始化父类
  • 一个类初始化就是要执行()方法
    • ()方法由静态类变量显示赋值代码和静态代码块组成
    • 类 变量显示赋值代码和静态代码块从上到下顺序执行
    • ()方法只执行一次
  • 基本执行流程

    • 主要是按照代码顺序执行静态方法->父类被调用的静态方法->父类的静态代码块—>子类被调用的静态方法—>子类的静态代码块—>子类被调用的非静态方法—>父类的非静态代码块—>父类构造方法—>父类中被子类重写的方法(在这里就是指父类中的 int i = test();)—>子类的非静态代码块—>子类的构造方法

      三、实例初始化过程

      实例初始化就是执行()方法
      下面所指的实例对象可以理解为 A a = new A(),这就是创建一个实例对象
      1、() 方法可能重载有多个,有几个构造器就有几个方法
      2、()方法由非静态实例变量显示赋值代码和非静态代码块、对应构造器代码组成
      3、非静态实例变量显示赋值代码和非静态代码块 代码从上到下顺序执行,而对应构造器的代码最后执行
      4、每次创建实例对象,调用对应构造器,执行的就是对应的()方法
      5、方法的首行是super()或super(参数列表),即对应父类的方法

      四、方法的重写

      override
  • 哪些方法不可以被重写

    • final方法
    • 静态方法
    • private等子类中不可见的方法
  • 对象的多态

    • 子类如果重写的父类的方法,那么通过子类调用的一定是子类重写过的代码
    • 非静态方法默认的调用对象是this
    • this对象在构造器或者说方法中就是正在创建的对象

      五、其他

  • Override和overload的区别

    • Override重写的要求?
      • 方法名 :相同
      • 形参列表:相同
      • 返回值类型:相同
      • 抛出异常列表:相同
      • 修饰符:可以子类可以扩大访问权限
    • overload的要球
      • 方法名:相同
      • 形参列表:必须不同
      • 返回值类型:可以不同
      • 抛出异常列表:可以不同
      • 修饰符:可以不同
    • 注意:
      • 如果某一方法在父类中是访问权限是 private,那么就不能在子类对其进行重载;如果定义的话,也只是定义了一个新方法,而不会达到重载的效果
  • 了解《JVM虚拟机规范》中关于方法的说明,invokespecial指令。
  • 什么是实例,什么是对象?
    • 对象是抽象的说法,你可以把它看作一个符合它自身定义的所有实例的代表,而实例则是对象的现实体现。你可以说一个实例是一个对象,但你不能说一个对象是一个实例。因为定义对象时只是把自身的规则和逻辑定义好,实例可以通过输入不同的数据使得自己和其他实例不同。
    • 比如:你可以定义一个Wheel.java,它是对象;而Test.java中可以定义两个wheel的实例
      • Wheel wheel1 = new Wheel(3); 这个是一个Wheel实例
      • Wheel wheel2 = new Wheel(5); 这个是另一个Wheel实例

image.png