Java对象初始化顺序(一)


  偶尔翻到了关于Java对象初始化顺序的面试题,重新复习了一下,顺便做笔记。

1.父类子类构造函数执行的先后顺序

public class Test2 {

    public int Field;

    //step 1
    public Test2(){

        Field = 1;
    }
}

/*************************************************/

/**
 * 次类的目的仅是为了验证父类子类构造函数执行的先后顺序
 */
public class Test3  extends Test2{

    //step 2
    public Test3(){

        Field = 2;
    }

    public static void main(String[] args) {

        Test3 t3 = new Test3();
        System.out.println("对象t3中字段的值是【" + t3.Field + "】");

        /************************************\
         * 输出结果
         * 对象t3中字段的值是【2】
         \************************************/
    }
}

结论:实例化一个对象,构造的执行顺序是由父类到子类的顺序,即Test2->Test3

2.构造函数初始化和内联方式初始化

/**
 * 此类目的仅是为了验证以内联的方式初始化字段和构造函数中初始化的
 * 字段的先后顺序
 *
 * 内联初始化的内联的意思,就是在声明字段的时候同时进行初始化赋值。
 */
public class Test1 {

    public int Field = 1;//step 1

    /**
     * step 2
     */
    public Test1() { Field = 2; } public static void main(String[] args) { Test1 t1 = new Test1(); System.out.println("对象t1中字段的值是【" + t1.Field + "】"); /************************************\ * 输出结果 * 对象t1中字段的值是【2】 \************************************/ } }

结论:实例化一个对象会先执行以内联方式初始化字段的代码,然后再去执行构造函数内的内容

3.初始化块和初始化块(静态)

public class Test5 {

    public static int Field;

    //初始化块(静态)
    static {

        Field = 1;
    }

    //初始化块
    {
        Field = 2;
    }

    public static void main(String[] args) {

        System.out.println("字段Field的值是【" + Field + "】");

        /*************************************\
         * 输出结果
         * 字段Field的值是【1】
        \*************************************/
    }
}

结论:初始化块要优先于静态初始化块执行(错误结论)

总感觉这个结论怪怪的,然后查了一些资料,得知初始化块只有在实例化一个对象的时候才会执行

public class Test5 {

    public static int Field;

    //初始化块(静态)
    static {

        Field = 1;
    }

    //初始化块
    {
        Field = 2;
    }

    public static void main(String[] args) {

        System.out.println("对象未被实例化之前,Field的值是【" + Field + "】");
        Test5 test5 = new Test5();
        System.out.println("对象被被实例化之后,Field的值是【" + Field + "】");

        //为了验证每次实例化对象都会调用初始化器
        Field = 3;
        System.out.println("给字段Field赋值,Field的值是【" + Field + "】");
        Test5 test5_0 = new Test5();
        System.out.println("再次实例化对象之后,Field的值是【" + Field + "】");
        /*************************************\
         *对象未被实例化之前,Field的值是【1】
         *对象被被实例化之后,Field的值是【2】
         *给字段Field赋值,Field的值是【3】
         *再次实例化对象之后,Field的值是【2】
         \*************************************/
    }
}

 

为了验证上边提到的红色字体部分正确性,还特意的将Field的值赋值为3并再次实例化 对象

结论:初始化器只有当被实例化的时候才会执行,并且每次实例化都会执行,静态初始化器有先于初始化器执行

 4.面试题一

public class Test6 {

    public static int i = Test7.j;

    {
        i++;
    }

    static {
        i = 0;
    }

    public Test6() {
        i++;
    }
}
/*********************************************/
public class Test7 extends Test6 {

    public static int j = Test6.i;

    static {
        j++;
    }

    {
        j++;
    }
}
/********************************************/
public class Main {

    public static void main(String[] args) {

        Test7 t7 = new Test7();
        System.out.println("字段I的值是【" + Test6.i + "");
        System.out.println("字段J的值是【" + Test7.j + "");
    }
}

5.面试题二

public class Test6 {

    public static int i = Test7.j;

    {
        i++;
    }

    static {
        i = 0;
    }

    public Test6() {
        i++;
    }
}
/*********************************************/
public class Test7 {

    public static int j = Test6.i;

    static {
        j++;
    }

    {
        j++;
    }
}
/*********************************************/
public class Main {

    public static void main(String[] args) {

        Test7 t7 = new Test7();
        System.out.println("字段I的值是【" + Test6.i + "】");
        System.out.println("字段J的值是【" + Test7.j + "】");
    }
}

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM