Java类(Class)的初始化顺序详解
前言
2021年面试腾讯高级,最后一道题Review代码,被问及这个问题,堪称经典。先贴代码和执行结果看现象,咱们再来分析解释现象。
一:Review代码如下:
Body.java
public class Body {
public boolean smile;
}
Lifecycle.java
public abstract class Lifecycle<T extends Object> {
public Lifecycle(T t) {
initData(t);
}
public abstract void initData(T t);
public abstract boolean needSmile();
}
Lifecycle.java
public abstract class Lifecycle<T extends Object> {
public Lifecycle(T t) {
initData(t);
}
public abstract void initData(T t);
public abstract boolean needSmile();
}
BlackBody.java
public class BlackBody extends Lifecycle<Body> {
private boolean needSmile = false;
public BlackBody(Body body) {
super(body);
}
@Override
public void initData(Body body) {
this.needSmile = body.smile;
System.out.println("initData阶段>>>needSmile=" + needSmile);
}
@Override
public boolean needSmile() {
System.out.println("needSmile阶段>>>needSmile=" + needSmile);
return needSmile;
}
}
TestBody.java
public class TestBody {
public static void main(String[] args) {
System.out.println("-------------------------------------");
Body body = new Body();
body.smile = true;
BlackBody blackBody = new BlackBody(body);
if (blackBody.needSmile()) {
System.out.println("black body smile");
} else {
System.out.println("black body needn't smile");
}
System.out.println("-------------------------------------");
}
}
上述代码,能输出"black body smile"吗?为什么?
可能你觉得能输出"black body smile",但是你也会怀疑那么这问题也太简单了吧。执行程序后打印结果如下;
打印结果是:“black body needn’t smile”,那么就意味着blackBody.needSmile()为false;
然后我们在程序关键位置initData方法和needSmile方法加入代码把needSmile输出控制台;结果如下:
1.initData方法执行时确实是 创建BlackBody对象时传参Body设置的true;
2.但是执行到needSmile方法时,变量needSmile的值被变量needSmile的默认值替换掉了为false;
这个问题就是考察类的执行顺序,然后做了个升级版,继承了抽象父类;
二:Class类执行顺序分析
代码演示:
public class Parent {
private static String static_field = "父类静态成员";
private String field = "父类非静态成员";
static {
System.out.println(static_field);
System.out.println("父类静态代码块");
}
{
System.out.println(field);
System.out.println("父类非静态代码块");
}
public Parent() {
System.out.println("父类构造函数");
}
public static void main(String[] args) {
new Parent();
}
}
public class Children extends Parent {
private static String static_field = "子类静态成员";
private String field = "子类非静态成员";
static {
System.out.println(static_field);
System.out.println("子类静态代码块");
}
{
System.out.println(field);
System.out.println("子类非静态代码块");
}
public Children() {
System.out.println("子类构造函数");
}
}
执行:
1.先后顺序依次为:父类静态>>>子类静态>>>父类非静态>>>父类构造函数>>>子类非静态>>>子类构造函数;
三:问题分析
创建BlackBody对象后,body携带的参数smile = true;先执行了父类Lifecycle的构造函数,Lifecycle的构造函数中调用了initData, initData执行;子类initData执行,所以needSmile为true;
当父类构造函数执行完之后,子类开始执行普通成员变量 private boolean needSmile = false;由于needSmile的初始默认值为false;即便父类给needSmile赋值为true了;但是needSmile又重新被赋值为默认值false;
所以needSmile的值出现了短暂的true后又成为false;这是由于类执行时的先后顺序导致的;根据这个原因,我们去掉needSmile的默认值即声明变量boolean needSmile;当java检测到needSmile未被赋默认值,会使用父类给needSmile赋的值true;这样程序就能输出“black body smile”
如下去掉BlackBody.java中的private boolean needSmile的默认值后,执行结果:
转载请声明出处,欢迎关注公众号一起探讨编程的乐趣、加入我们贡献技术和高质量代码!