1 题目
问:main 方法执行后,最终输出的结果。
1.1 结果
2 分析
本题设计三个方面的知识
- 类的初始化
- 一个类要创建实例,需要先加载并初始化该类
- main方法所在的类需要先加载和初始化
- 一个子类要初始化,需要先初始化父类
- 类的初始化就是执行<clinit>() 方法
- <clinit>() 方法由静态类变量显示赋值代码和静态代码块组成
- 类变量显示赋值和静态代码块是从上到下执行的
- <clinit>() 方法只会执行一次
- 实例初始化
- 实例初始化就是执行<init>() (构造器)方法
- <init>() 方法可能有重载多个,有几个构造器就有几个<init>() 方法
- <init>() 方法由非静态实例变量显示赋值代码和非静态代码块、对应的构造器组成
- 非静态实例显示赋值代码和非静态代码块是从上到下顺序执行的,构造器最后执行
- 每次创建对象,都会调用对应的构造器,执行的就是<init>()方法
- <init>() 方法的首行是super,就是对应父类的<init>() 方法
- 方法的重写
- 哪些方法不可以被重写
- final修饰的
- 静态方法
- private 等子类不可见的方法
- 对象的多态性
- 子类如果重写了父类的方法,调用子类方法,一定执行的是子类重写过的代码
- 非静态方法默认的调用对象是this
- this 对象在构造器或者说是<init>()方法 就是正在创建的对象
3 根据上述分析,分析题目
- 首先是类初始化,先初始化父类,然后执行静态显示赋值语句 j = method() ,
- 因此输出 (5)
- 然后执行静态代码块
- 输出 (1)
- 然后再初始化子类,同理,输出 (10) (6)
- 然后实例初始化
- 先执行父类的<init>方法,执行非静态显示赋值语句, i = test() ,由于i 是非静态方法,因此前面默认是this,此时调用者是子类,因此会执行子类重写的test方法,
- 输出 (9)
- 然后再执行父类的非静态代码块
- 输出(3)
- 最后执行父类的构造器
- 输出(2)
- 然后执行子类中的代码,同理,输出
- 输出(9)(8)(7)
- 接下来是第二个创建实例,会再次调用<init>方法,因此(9)(3)(2)(9)(8)(7) 会再次输出