java类初始化顺序--结论&&试验

最近找工作,经常遇到笔试题上关于类初始化的题目,涉及到静态代码块,非静态代码块以及构造函数的加载顺序问题。今天复习了以前的笔记,来整理一下。

先给结论:
(1)对于单个类,没有new对象时,执行顺序为先执行静态代码块/初始化静态变量(按照顺序)。
(2)对于单个类,有new对象时,执行顺序为先执行静态代码块/初始化静态变量(按照顺序),然后非静态代码块/ 非静态变量(常量),最后构造函数。
(3)对于static修饰的代码块或者变量,只初始化一次。第二次new对象不会再执行。
(a)对于有继承关系的类,没有new对象时,执行顺序为先执行父类静态代码块/初始化静态变量(按照顺序),再执行子类静态代码块/初始化静态变量(按照顺序)。
(b)对于有继承关系的类,有new对象时,执行顺序为先执行父类静态代码块、子类静态代码块,然后父类非静态代码块/ 非静态变量(常量)和构造函数、子类非静态代码块和构造函数。
(c)对于有继承关系的类,对于static修饰的代码块或者变量,只初始化一次。第二次new对象不会再执行。
<static只能出现在在类中,不能在方法里面。>

结论(1)试验:

public class ExcuteOrderTest {

    public ExcuteOrderTest(){
        System.out.println("构造函数!");
    }
    {
        _i ++;
        System.out.println("非静态代码块::"+_i);
    }
    public static int _i = 10;
    static {
        _i  = _i +2;
        System.out.println("静态代码块::"+_i);
    }

    public static void main(String[] args) {
//        ExcuteOrderTest test = new ExcuteOrderTest();
//      System.out.println(_i);
//      ExcuteOrderTest test1 = new ExcuteOrderTest();
//      System.out.println(_i);
        }
}

/**
输出:
静态代码块::12

分析:
可以看出没有new对象时,先执行的静态代码块,而且没有执行非静态代码块和构造函数。
**/

结论(2)试验:

public class ExcuteOrderTest {

    public ExcuteOrderTest(){
        System.out.println("构造函数!");
    }
    {
        _i ++;
        System.out.println("非静态代码块::"+_i);
    }
    public static int _i = 10;
    static {
        _i  = _i +2;
        System.out.println("静态代码块::"+_i);
    }

    public static void main(String[] args) {
        ExcuteOrderTest test = new ExcuteOrderTest(); //
//      System.out.println(_i);
//      ExcuteOrderTest test1 = new ExcuteOrderTest();
//      System.out.println(_i);
        }
}

/**
输出:
静态代码块::12
非静态代码块::13
构造函数!

分析:
当new一个对象时,即使构造函数、非静态代码块(构造块)、静态代码块编写顺序打乱,执行顺序还是先静态代码块、非静态代码块、构造函数。对照试验就不贴上来了。
**/

** 结论(3)试验:**

public class ExcuteOrderTest {

    public ExcuteOrderTest(){
        System.out.println("构造函数!");
    }
    {
        _i ++;
        System.out.println("非静态代码块::"+_i);
    }
    public static int _i = 10;
    static {
        _i  = _i +2;
        System.out.println("静态代码块::"+_i);
    }

    public static void main(String[] args) {
        ExcuteOrderTest test = new ExcuteOrderTest();
      System.out.println(_i);
      ExcuteOrderTest test1 = new ExcuteOrderTest();
      System.out.println(_i);
        }
}

/**
输出:
静态代码块::12
非静态代码块::13
构造函数!
13
非静态代码块::14
构造函数!
14

分析:
可以看到,在第二次new对象test1时,是没有重新执行静态变量初始化,以及静态代码块中的++操作的。
**/

下面试验的父类

public class ExcuteOrderTestParent {
    public ExcuteOrderTestParent(){
        System.out.println("ExcuteOrderTestParent构造函数!");
    }
    {
        _i ++;
        System.out.println("ExcuteOrderTestParent非静态代码块::::"+_i);
    }
    public static int _i = 20;
    static {
        _i  = _i +2;
        System.out.println("ExcuteOrderTestParent::静态代码块::"+_i);
    }
}

结论(a)试验:

public class ExcuteOrderTest extends ExcuteOrderTestParent {

    public ExcuteOrderTest(){
        System.out.println("ExcuteOrderTest构造函数!");
    }
    {
        _i ++;
        System.out.println("ExcuteOrderTest非静态代码块::"+_i);
    }
    public static int _i = 10;
    static {
        _i  = _i +2;
        System.out.println("ExcuteOrderTest静态代码块::"+_i);
    }
    public static void main(String[] args) {
//        ExcuteOrderTest test = new ExcuteOrderTest();
//      ExcuteOrderTest test1 = new ExcuteOrderTest();

        }
}

/**
输出:
ExcuteOrderTestParent::静态代码块::22
ExcuteOrderTest静态代码块::12

分析:
在没有new对象的时候,会只执行静态代码块,而且是先父类后子类。非静态代码块和构造方法不执行。
**/

结论(b)试验:

public class ExcuteOrderTest extends ExcuteOrderTestParent {

    public ExcuteOrderTest(){
        System.out.println("ExcuteOrderTest构造函数!");
    }
    {
        _i ++;
        System.out.println("ExcuteOrderTest非静态代码块::"+_i);
    }
    public static int _i = 10;
    static {
        _i  = _i +2;
        System.out.println("ExcuteOrderTest静态代码块::"+_i);
    }

    public static void main(String[] args) {
      ExcuteOrderTest test = new ExcuteOrderTest();
//      ExcuteOrderTest test1 = new ExcuteOrderTest();

        }
}

/**
输出:
ExcuteOrderTestParent::静态代码块::22
ExcuteOrderTest静态代码块::12
ExcuteOrderTestParent非静态代码块::::23
ExcuteOrderTestParent构造函数!
ExcuteOrderTest非静态代码块::13
ExcuteOrderTest构造函数!
**/

结论(c)试验:

public class ExcuteOrderTest extends ExcuteOrderTestParent {

    public ExcuteOrderTest(){
        System.out.println("ExcuteOrderTest构造函数!");
    }
    {
        _i ++;
        System.out.println("ExcuteOrderTest非静态代码块::"+_i);
    }
    public static int _i = 10;
    static {
        _i  = _i +2;
        System.out.println("ExcuteOrderTest静态代码块::"+_i);
    }

    public static void main(String[] args) {
      ExcuteOrderTest test = new ExcuteOrderTest();
      ExcuteOrderTest test1 = new ExcuteOrderTest();
        }
}
/**
输出:
ExcuteOrderTestParent::静态代码块::22
ExcuteOrderTest静态代码块::12
ExcuteOrderTestParent非静态代码块::::23
ExcuteOrderTestParent构造函数!
ExcuteOrderTest非静态代码块::13
ExcuteOrderTest构造函数!
ExcuteOrderTestParent非静态代码块::::24
ExcuteOrderTestParent构造函数!
ExcuteOrderTest非静态代码块::14
ExcuteOrderTest构造函数!
**/

参考文献(很透彻):https://www.jianshu.com/p/55c86e6c5c60

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值