类初始化和实例初始化
题目:输出以下代码的结果:
子类:
public class Father {
private int i = test();
private static int j = method();
static{
System.out.print("(1)");
}
Father(){
System.out.print("(2)");
}
{
System.out.print("(3)");
}
public int test(){
System.out.print("(4)");
return 1;
}
public static int method(){
System.out.print("(5)");
return 1;
}
}
父类:
public class Son extends Father{
private int i = test();
private static int j = method();
static{
System.out.print("(6)");
}
Son(){
System.out.print("(7)");
}
{
System.out.print("(8)");
}
public int test(){
System.out.print("(9)");
return 1;
}
public static int method(){
System.out.print("(10)");
return 1;
}
public static void main(String[] args) {
Son s1 = new Son();
System.out.println();
Son s2 = new Son();
}
}
输出结果为:
(5)(1)(10)(6)(9)(3)(2)(9)(8)(7)
(9)(3)(2)(9)(8)(7)
本题主要考点:
- 类初始化过程
- 实例初始化过程
- 方法重写
下面分别说明:
(1)类初始化过程
- 一个类要创建实例,需要先加载并初始化该类
– main()方法所在的类需要先加载和初始化 - 一个类要初始化,需要先初始化父类
- 类初始化,就是执行
<clinit>()
方法
–<clinit>()
方法是由编译器帮我们生成的
–<clinit>()
方法由静态类变量的显式赋值代码和静态代码块组成
– 静态类变量的显式赋值代码和静态代码块,从上到下顺序执行
–<clinit>()
方法只执行一次
(2)实例初始化过程
- 实例初始化过程是执行
<init>()
方法 <init>()
方法由super()/super(参数)、非静态实例变量显式赋值代码、非静态代码块、构造器代码等四部分组成,执行顺序是:
– super()/super(参数),这个方法即时在源代码中不写,编译后的字节码也是有这个方法的
– 非静态实例变量显式赋值代码和非静态代码块,从上到下顺序执行
– 构造器代码- 每次创建实例对象,都执行一次
<init>()
方法
(3)方法重写:
哪些方法不可以被重写:
- final方法
- static方法
- private等子类中不可见方法
对象的多态性:
- 子类如果重写了父类的方法,通过子类对象调用的一定是子类重写过的代码
- 非静态方法默认的调用对象是this
- this对象在
<init>()
方法中就是正在创建的对象
上面提到,实例化init()
方法的第一步是super()/super(参数),在本例中,Son类的super()会执行Father类的init()
方法,执行过程中一个test()方法,但是这个方法被Son重写了,所以执行时会调用Son类自己的test()方法,这里要注意。