面试题:
如下两个类的代码
/*父类对象*/
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();
}
}
问题:
- 执行Son类的main函数,控制台打印的结果是什么?
- 如果main方法什么都不写,控制台打印的结果是什么?
结果
第一题答案:
(5)(1)(10)(6)(9)(3)(2)(9)(8)(7)
(9)(3)(2)(9)(8)(7)
第二题答案:
(5)(1)(10)(6)
你是否答对了?
类的初始化过程
要使用到一个类对其进行实例化
就需要先对类进行初始化
,而且类的初始化只执行一次!这个特点可以做单例模式
类的初始化就是将静态成员变量
和静态代码块
进行初始化,静态代码块和静态成员变量的执行顺序按照代码的先后顺序执行,谁在上面就谁先执行初始化!
注意:main方法所在的类先加载和初始化,该类的初始化又要先初始化父类
也就是说最先初始化的类是父类的静态代码块或者静态成员变量
,然后是子类的静态代码块或者静态成员变量
静态代码块和静态成员变量的先后顺序由代码先后顺序影响
实例化的初始化过程
一个类要进行实例化,就需要先对类初始化
然后再实例化,实例化又需要先实例化父类,后实例化子类
实例化需要初始化非静态成员变量
和非静态代码块
,非static的成员变量和代码块的先后顺序也是谁先声明谁先执行。
最后执行构成方法
总结
整体的初始化排序
类初始化 > 实例化初始化
**父类**静态成员变量 或 静态代码块(顺序由声明先后顺序定)
>
**子类**静态成员变量 或 静态代码块(顺序由声明先后顺序定)
>
**父类**非静态成员变量 或 非静态代码块(顺序由声明先后顺序定)
>
父类构造方法
>
**子类**非静态成员变量 或 非静态代码块(顺序由声明先后顺序定)
>
子类构造方法
如果以16进制的方式去查看编译后的class文件会发现有<clinit>、<init>等方法
而<clinit>()就是进行类初始化执行的指令,里面由 静态类成员变量显示赋值 和 静态代码块 组成,里面的顺序按照声明顺序先后执行
<init>()可能有多个,因为有无参构造器和有参构造器,有几个构造器就有几个<init>()。是执行示例化初始化的指令,里面由 非静态类成员变量显示赋值 和 非静态代码块 组成,里面的顺序按照声明顺序先后执行,<init>()首行一定是super();构造器里的代码最后执行。每一次实例化都执行一次<init>()