第二篇:一文搞懂成员变量初始化

一、前言

二、局部变量和类变量的不同处理

Java语言中,所有变量使用前都会进行适当的初始化,即尽量确保变量使用之前有一个合理的值。

对于局部变量,使用编译时检查来确保初始化的完成,示意如下:

void f(){
	int i;
	i++;//编译报错  局部变量未初始化
}

对于数据成员变量,基本类型(8种)有相应的默认初始值,引用类型(3种 类 接口 数组)默认初始值为null,如下表:

基本类型默认值
byte0
short0
int0
long0
float0.0
double0.0
booleanfalse
char‘\u0000’(null)

小结:Java变量初始化
对于局部变量,定义时初始化,否则编译不过;
对于数据成员变量,定义时可以不初始化,赋予默认值,基本类型(8种)有相应的默认初始值,引用类型(3种 类 接口 数组)默认初始值为null。

三、初始化顺序

关于Java中变量的初始化顺序,其语言本身有一套自有逻辑,示意如下:

3.1 非静态域与方法(标准答案:非静态域>main方法函数调用)

public class InitializationTest {
    A a1 = new A(1);

    public InitializationTest() {
        System.out.println("IntializationTest()");

    }

    A a2 = new A(2);

    public static void main(String[] args) {

        InitializationTest initializationTest = new InitializationTest();
        initializationTest.fTest();

    }

    void fTest() {
        System.out.println("fTest()");
    }

    A a3 = new A(3);
}

class A {
    A(int sign_Number) {
        System.out.println("A()  " + sign_Number);
    }
}

​ 输出结果:

A()  the first nonstatic object
A()  the second nonstatic object
A()  the third nonstatic object
IntializationTest()
fTest()

小结:初始化顺序:非静态域>main方法函数调用
第一,域与方法调用顺序,非静态域>main方法函数调用,Java中域的初始化先于主函数main()调用,又因为main()式程序入口地址,故所有域的初始化先于所有方法(包括构造器)的调用;
第二,域与域之间初始化顺序,根据代码中定义域的先后顺序来确定。

3.2 非静态域、代码块与方法(标准答案:非静态域、非静态代码段>main方法函数调用)

public class InitializationTest {
    A a1 = new A("the first nonstatic object");

    {    // 非静态代码块
        System.out.println("the first nonstatic code block");
    }

    public InitializationTest() {   // 构造函数
        System.out.println("IntializationTest()");
    }

    A a2 = new A("the second nonstatic object");

    {  // 非静态代码块
        System.out.println("the second nonstatic code block");
    }

    public static void main(String[] args) {
        InitializationTest initializationTest = new InitializationTest();
        initializationTest.fTest();
    }

    void fTest() {
        System.out.println("fTest()");
    }

    {    // 非静态代码块
        System.out.println("the third nonstatic code block");
        // 这里将代码块3放在a3之前,证明代码块和域的初始化同级,按代码顺序初始化
    }

    A a3 = new A("the third nonstatic object");
}

class A {
    A(String description) {   // 构造函数
        System.out.println("A()  " + description);
    }
}

输出:

A()  the first nonstatic object
the first nonstatic code block
A()  the second nonstatic object
the second nonstatic code block
the third nonstatic code block
A()  the third nonstatic object
IntializationTest()
fTest()

小结:非静态域、非静态代码段>main方法函数调用
第一,代码块和域的初始化同级,域与代码块之间初始化顺序,根据代码中定义的先后顺序来确定;
第二,初始化顺序:非静态域、非静态代码段>main方法函数调用。

3.3 静态域、静态代码块、非静态域、非静态代码块与方法(标准答案:静态域、静态代码块>非静态域、非静态代码块>main方法函数调用)

加入静态域、静态代码块后:

public class InitializationTest {
    static A a1_static = new A("the first static object");
    A a1 = new A("the first nonstatic object");

    {
        System.out.println("the first nonstatic code block");
    }

    static {
        System.out.println("the first static code block");
    }

    public InitializationTest() {
        System.out.println("IntializationTest()");

    }

    A a2 = new A("the second nonstatic object");
    static A a2_static = new A("the second static object");

    {
        System.out.println("the second nonstatic code block");
    }

    static {
        System.out.println("the second static code block");
    }

    public static void main(String[] args) {

        InitializationTest initializationTest = new InitializationTest();
        initializationTest.fTest();
        System.out.println("=========分割线============");
        new InitializationTest();// 再次新建对象 证明InitializationTest中三个静态代码段仅初始化一次
    }

    void fTest() {
        System.out.println("fTest()");
    }

    {
        System.out.println("the third nonstatic code block");
        // 这里将代码块3放在a3之前,证明代码块和域的初始化同级,按代码顺序初始化
    }

    static {
        System.out.println("the third static code block");
    }

    A a3 = new A("the third nonstatic object");
    static A a3_static = new A("the third static object");

}

class A {  //用来提供InitializationTest的一个域
    A(String description) {
        System.out.println("A()  " + description);
    }
}

输出:

A()  the first static object
the first static code block
A()  the second static object
the second static code block
the third static code block
A()  the third static object
A()  the first nonstatic object
the first nonstatic code block
A()  the second nonstatic object
the second nonstatic code block
the third nonstatic code block
A()  the third nonstatic object
IntializationTest()
fTest()
=========分割线============
A()  the first nonstatic object
the first nonstatic code block
A()  the second nonstatic object
the second nonstatic code block
the third nonstatic code block
A()  the third nonstatic object
IntializationTest()

小结:静态域、静态代码块>非静态域、非静态代码块>main方法函数调用
第一,静态域与静态代码块之间初始化顺序,根据代码中定义的先后顺序来确定,非静态域与非静态代码块之间初始化顺序,亦根据代码中定义的先后顺序来确定,不同的是,新建n个某类对象时,该类静态成员仅初始化一次,非静态成员初始化n次;
第二,初始化顺序:静态域、静态代码块>非静态域、非静态代码块>main方法函数调用。

3.4 父类static成员、子类static成员、父类非static成员、子类非static成员(父类静态域、父类静态代码块>子类静态域、子类静态代码块>父类非静态域、父类非静态代码块>子类非静态域、子类非静态代码块>main方法函数调用)

加入父类后:

class Super {
    {
        System.out.println("the Super nostatic code block");
    }

    static {
        System.out.println("the Super static code block");
    }

}

public class InitializationTest extends Super {
    static A a1_static = new A("the first static object");
    A a1 = new A("the first nonstatic object");

    {
        System.out.println("the first nonstatic code block");
    }

    static {
        System.out.println("the first static code block");
    }

    public InitializationTest() {
        System.out.println("IntializationTest()");

    }

    A a2 = new A("the second nonstatic object");
    static A a2_static = new A("the second static object");

    {
        System.out.println("the second nonstatic code block");
    }

    static {
        System.out.println("the second static code block");
    }

    public static void main(String[] args) {
        InitializationTest initializationTest = new InitializationTest();
        initializationTest.fTest();
        System.out.println("=========分割线============");
        new InitializationTest();// 再次新建对象 证明InitializationTest中三个静态代码段仅初始化一次
    }

    void fTest() {
        System.out.println("fTest()");
    }

    {
        System.out.println("the third nonstatic code block");
        // 这里将代码块3放在a3之前,证明代码块和域的初始化同级,按代码顺序初始化
    }

    static {
        System.out.println("the third static code block");
    }

    A a3 = new A("the third nonstatic object");
    static A a3_static = new A("the third static object");

}

class A {  //用来提供InitializationTest的一个域
    A(String description) {
        System.out.println("A()  " + description);
    }
}

输出:

the Super static code block
A()  the first static object
the first static code block
A()  the second static object
the second static code block
the third static code block
A()  the third static object
the Super nostatic code block
A()  the first nonstatic object
the first nonstatic code block
A()  the second nonstatic object
the second nonstatic code block
the third nonstatic code block
A()  the third nonstatic object
IntializationTest()
fTest()
=========分割线============
the Super nostatic code block
A()  the first nonstatic object
the first nonstatic code block
A()  the second nonstatic object
the second nonstatic code block
the third nonstatic code block
A()  the third nonstatic object
IntializationTest()

小结:
第一,静态域与静态代码块之间初始化顺序,根据代码中定义的先后顺序来确定,非静态域与非静态代码块之间初始化顺序,亦根据代码中定义的先后顺序来确定,值得注意的是,父类成员先于子类成员初始化;
第二,初始化顺序:父类静态域、父类静态代码块>子类静态域、子类静态代码块>父类非静态域、父类非静态代码块>子类非静态域、子类非静态代码块>main方法函数调用。

四、面试金手指

4.1 局部变量和类变量

金手指:Java变量初始化
(1)对于局部变量,定义时初始化,否则编译不过;
(2)对于数据成员变量,定义时可以不初始化,赋予默认值,基本类型(8种)有相应的默认初始值,引用类型(3种 类 接口 数组)默认初始值为null。

4.2 成员变量初始化

1、非静态域与方法(标准答案:非静态域>main方法函数调用);
2、非静态域、代码块与方法(标准答案:非静态域、非静态代码段>main方法函数调用);
3、 静态域、静态代码块、非静态域、非静态代码块与方法(标准答案:静态域、静态代码块>非静态域、非静态代码块>main方法函数调用);
4、父类static成员、子类static成员、父类非static成员、子类非static成员 (父类静态域、父类静态代码块>子类静态域、子类静态代码块>父类非静态域、父类非静态代码块>子类非静态域、子类非静态代码块>main方法函数调用)。

五、尾声

一文搞懂成员变量初始化,完成了。

天天打码,天天进步!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

祖母绿宝石

打赏一下

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值