偶尔翻到了关于Java对象初始化顺序的面试题,重新复习了一下,顺便做笔记。
1.父类子类构造函数执行的先后顺序
public classTest2 {public intField;//step 1
publicTest2(){
Field= 1;
}
}/*************************************************/
/*** 次类的目的仅是为了验证父类子类构造函数执行的先后顺序*/
public class Test3 extendsTest2{//step 2
publicTest3(){
Field= 2;
}public static voidmain(String[] args) {
Test3 t3= newTest3();
System.out.println("对象t3中字段的值是【" + t3.Field + "】");/************************************\
* 输出结果
* 对象t3中字段的值是【2】
\************************************/}
}
结论:实例化一个对象,构造的执行顺序是由父类到子类的顺序,即Test2->Test3
2.构造函数初始化和内联方式初始化
/**
* 此类目的仅是为了验证以内联的方式初始化字段和构造函数中初始化的
* 字段的先后顺序
*
* 内联初始化的内联的意思,就是在声明字段的时候同时进行初始化赋值。
*/
public classTest1 {
public int Field = 1;//step 1
/**
* step 2
*/
publicTest1() {
Field = 2;
}
public static voidmain(String[] args) {
Test1 t1 = newTest1();
System.out.println("对象t1中字段的值是【" + t1.Field + "】");
/************************************\
* 输出结果
* 对象t1中字段的值是【2】
\************************************/}
}
结论:实例化一个对象会先执行以内联方式初始化字段的代码,然后再去执行构造函数内的内容
3.初始化块和初始化块(静态)
public classTest5 {public static intField;//初始化块(静态)
static{
Field= 1;
}//初始化块
{
Field= 2;
}public static voidmain(String[] args) {
System.out.println("字段Field的值是【" + Field + "】");/*************************************\
* 输出结果
* 字段Field的值是【1】
\*************************************/}
}
结论:初始化块要优先于静态初始化块执行(错误结论)
总感觉这个结论怪怪的,然后查了一些资料,得知初始化块只有在实例化一个对象的时候才会执行
public classTest5 {public static intField;//初始化块(静态)
static{
Field= 1;
}//初始化块
{
Field= 2;
}public static voidmain(String[] args) {
System.out.println("对象未被实例化之前,Field的值是【" + Field + "】");
Test5 test5= newTest5();
System.out.println("对象被被实例化之后,Field的值是【" + Field + "】");//为了验证每次实例化对象都会调用初始化器
Field = 3;
System.out.println("给字段Field赋值,Field的值是【" + Field + "】");
Test5 test5_0= newTest5();
System.out.println("再次实例化对象之后,Field的值是【" + Field + "】");/*************************************\
*对象未被实例化之前,Field的值是【1】
*对象被被实例化之后,Field的值是【2】
*给字段Field赋值,Field的值是【3】
*再次实例化对象之后,Field的值是【2】
\*************************************/}
}
为了验证上边提到的红色字体部分正确性,还特意的将Field的值赋值为3并再次实例化 对象
结论:初始化器只有当被实例化的时候才会执行,并且每次实例化都会执行,静态初始化器有先于初始化器执行
4.面试题一
public classTest6 {public static int i =Test7.j;
{
i++;
}static{
i= 0;
}publicTest6() {
i++;
}
}/*********************************************/
public classTest7 extends Test6 {public static int j =Test6.i;static{
j++;
}
{
j++;
}
}/********************************************/
public classMain {public static voidmain(String[] args) {
Test7 t7= newTest7();
System.out.println("字段I的值是【" + Test6.i + "】");
System.out.println("字段J的值是【" + Test7.j + "】");
}
}
5.面试题二
public class Test6 {
public staticint i =Test7.j;
{
i++;
}
static {
i= 0;
}
public Test6() {
i++;
}
}/*********************************************/public class Test7 {
public staticint j =Test6.i;
static {
j++;
}
{
j++;
}
}/*********************************************/public class Main {
public staticvoidmain(String[] args) {
Test7 t7= newTest7();
System.out.println("字段I的值是【" + Test6.i + "】");
System.out.println("字段J的值是【" + Test7.j + "】");
}
}
本文详细探讨了Java中对象初始化的顺序,包括父类与子类构造函数的执行顺序、构造函数与字段内联初始化的执行顺序、初始化块与静态初始化块的执行时机。通过实例代码分析得出结论:构造函数执行从父类到子类;字段内联初始化先于构造函数执行;静态初始化块在类加载时执行,而普通初始化块在对象实例化时执行,并且每次实例化都会执行。文章最后给出了两个面试题,进一步加深了对这些概念的理解。
413

被折叠的 条评论
为什么被折叠?



