一道面试题:考察类的初始化顺序

题目:

public class Test{

    public static int k = 0;

    public static Test t1 = new Test("t1");

    public static Test t2 = new Test("t2");

    public static int i = print("i");

    public static int n = 99;

    private int a = 0;

    public int j = print("j");

    {

        print("构造代码块");

    }

    static{

        print("静态代码块");

    }

    public Test(String str){

        System.out.println((++k)+":"+str+"  i="+i+"  n="+n);

        ++i;

        ++n;

    }

    private static int print(String str){

        System.out.println((++k)+":"+str+"  i="+i+"  n="+n);

        ++n;

        return++i;

    }

    public static void main(String[] args) {

        Test t = new Test("init");

    }

}

输出结果为:

1:j  i=0  n=0

2:构造块  i=1  n=1

3:t1  i=2  n=2

4:j  i=3  n=3

5:构造块  i=4  n=4

6:t2  i=5  n=5

7:i  i=6  n=6

8:静态块  i=7  n=99

9:j  i=8  n=100

10:构造块  i=9  n=101

11:init  i=10  n=102

分析:

1、声明静态变量,并赋值为变量类型默认值:k=0    t1=null    t2=null    i=0    n=0。

2、初始化静态变量:k=0。

3、初始化静态变量:t1=new Test("t1")。此处实例化Test类时,会先定义非静态变量:a=0    j=0,紧接着,初始化非静态变量:a=0    j=print("j"),此处对j初始化时调用print方法,输出之前,k先自增,k=1,而后输出:1:j  i=0  n=0,同时,i=1    n=1。回到执行t1=new Test("t1"),调用Test构造方法前,先执行构造代码块,构造代码块调用print方法,输出之前,k先自增,k=2,而后输出:2:构造块  i=1  n=1 ,同时,i=2    n=2。继续执行t1=new Test("t1"),调用Test构造方法,输出之前,k先自增,k=3,而后输出:3:t1  i=2  n=2,同时,i=3    n=3。

4、初始化静态变量:t2=new Test("t2"),步骤同3。此处实例化Test类时,会先定义非静态变量:a=0    j=0,紧接着,初始化非静态变量:a=0    j=print("j"),此处对j初始化时调用print方法,输出之前,k先自增,k=4,而后输出:4:j  i=3  n=3,同时,i=4    n=4。回到执行t2=new Test("t2"),调用Test构造方法前,先执行构造代码块,构造代码块调用print方法,输出之前,k先自增,k=5,而后输出:5:构造块  i=4  n=4,同时i=5    n=5。继续执行t2=new Test("t2"),调用Test构造方法,输出之前,k先自增,k=6,而后输出:6:t2  i=5  n=5,同时i=5    n=5。

5、初始化静态变量:i=print("i")。调用print方法,输出之前,k先自增,k=7,而后输出:7:i  i=6  n=6,同时i=7    n=7。

6、初始化静态变量:n=99。

7、按照声明顺序,执行静态代码块:静态代码块调用print方法,输出之前,k先自增,k=8,而后输出:8:静态块  i=7  n=99,同时,i=8    n=100。

8、此时,静态变量初始化和静态代码块执行已完成。继续声明非静态变量,并赋值为变量类型默认值:a=0    j=0。

9、初始化非静态变量:a=0。

10、初始化非静态变量:j=print("j")。此处对j初始化时调用print方法,输出之前,k先自增,k=9,而后输出:9:j  i=8  n=100,同时,i=9    n=101。

11、此时,Test的加载已完成,继续执行Main方法中Test t=new Test("init")。调用Test构造方法前,先执行构造代码块,构造代码块调用print方法,输出之前,k先自增,k=10,而后输出:10:构造块  i=9  n=101,同时i=10    n=102。继续执行t=new Test("init"),调用Test构造方法,输出之前,k先自增,k=11,而后输出:11:init  i=10  n=102,同时i=11    n=103。

总结:

如存在类的继承:

1、先进行父类静态变量初始化和静态代码块执行,两者的执行顺序取决于声明的顺序。

2、再进行子类静态变量初始化和静态代码块执行,两者的执行顺序取决于声明的顺序。

3、再进行父类非静态变量初始化和非静态代码块执行,两者的执行顺序取决于声明的顺序。

4、再进行父类构造方法执行。

5、再进行子类非静态变量初始化和非静态代码块执行,两者的执行顺序取决于声明的顺序。

6、再进行子类构造方法执行。

7、静态代码块只在类加载时执行一次,构造代码块在每次调用类的构造方法实例化时都会执行一次。

以上,概括为:先子类后父类,先静态后非静态,先属性后方法,先声明后赋值。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 33,238评论 18 399
  • 总结 想清楚再编码 分析方法:举例子、画图 第1节:画图分析方法 对于二叉树、二维数组、链表等问题,都可以采用画图...
    M_巴拉巴拉阅读 4,948评论 0 7
  •   最近在看回顾Java基础的时候,发现看似很简单的类初始化的顺序却并不是那么简单(往往越是简单的东西反而越容易出...
    BrightLoong阅读 5,341评论 0 2
  • 1.把二元查找树转变成排序的双向链表 题目: 输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。 要求不...
    曲终人散Li阅读 8,651评论 0 19
  • 经历过欧亚学习交流分享之后,再一次对于我们的学习方法有了新的认识,在每一步的流程,我们都要有输入和产出。以下是我的...
    YKKKY阅读 1,634评论 1 1

友情链接更多精彩内容