关于 Java 类加载初始化
程序员文章站
2022-04-19 18:22:17
...
问:简单说说下面程序的运行结果?
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");
}
}
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);
}
}
public static void main (String[]args ){
System.out.println("------ new Child()");
Child cc = new Child();
System.out.println("\n------ cc.action()");
cc.action();
Base bb = c;
System.out.println("\n-------bb.action()");
bb.action();
System.out.println("\n ------- bb.s: " + bb.s);
System.out.println("\n ------- cc.s: " + cc.s);
}
答:输出结果如下:
------ new Child()
基类静态代码块, s:0
子类静态代码块, s:0 //子类静态代码块比父类构造方法先执行
基类实例代码块, a:0 //实例代码块比构造方法先执行
基类构造方法, a:1
子类实例代码块, a:0
子类构造方法,a:10
//对于变量无论是类变量还是实例变量都是静态绑定访问的。
------ cc.action()
start
child s: 10 , a: 20
end
//对于变量无论是类变量还是实例变量都是静态绑定访问的。
-------bb.action()
start
child s: 10 , a: 20
end
------- bb.s: 1
------- cb.s: 10
其实考察的是 Java 类加载与初始化,加载就是在第一次使用类时动态把类加载到内存,加载一个类会看其父类是否已经加载,如果没有则会先加载父类。类加载过程如下:分配内存保存类信息->给类变量赋默认值->加载父类->设置父子关系->执行类初始化代码;而类初始化过程(先执行父类再执行子类,父类执行时子类静态变量是有默认值 0 的)如下:定义静态变量时的赋值语句->静态初始化代码块;这些 OK 以后就进入实例初始化过程:定义实例变量时的赋值语句->实例初始化代码块->构造方法。 所以上面的结果基本就是这个流程,只是寻找要执行的实例方法时是从对象的实际类型信息开始查找的,找不到才会查父类;对于变量无论是类变量还是实例变量都是静态绑定访问的。
上一篇: SpringBoot(一)
下一篇: 关于数组的初始化问题! .