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的默认值后,执行结果:

在这里插入图片描述

转载请声明出处,欢迎关注公众号一起探讨编程的乐趣、加入我们贡献技术和高质量代码!
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值