手记

深入浅析Java成员变量初始化

要说起Java中成员变量的初始化,可以说是最基本的操作了,然而其中也大有文章,非常值得注意。

内联初始化

内联初始化是最简单的初始化方法,直接在声明成员变量的时候赋值初始化即可。

public class Bar {

    private int foo = 10;
    
}

内联初始化简洁明了,方便实用,但是如果变量初始化时需要异常处理、条件判断等复杂操作,就有心无力了。

构造函数初始化

如果初始化变量时有一些复杂的逻辑,比如首先正常取值,在取值失败时再采用默认值,这时可以考虑将其放到构造函数中:

public class Bar {

    private int foo;

    public Bar() {
        try {
            this.foo = Foo.getFoo();
        } catch (Exception e) {
            this.foo = 5;
        }
    }

}

同时,如果有多个构造函数,则应该将相同的部分放到一个函数中,在构造函数中复用。

public class Bar {

    private int foo;

    public Bar() {
        this.initFoo();
    }

    public Bar(int bar) {
        this.initFoo();
    }

    private void initFoo() {
        try {
            this.foo = Foo.getFoo();
        } catch (Exception e) {
            this.foo = 5;
        }
    }

}

注意到initFoo函数修饰符为private,因为如果它不是private或者final,根据Java多态的特性,如果Bar有了子类,并且子类override了initFoo方法,那么构造子类时,会自动调用Bar的构造方法,此时会调用子类的initFoo方法,产生意想不到的效果。
因此initFoo如果不需要被子类复用,可以设置为private,如果需要被子类复用,可以设置为protected final

初始化块

大家对于Java的static初始化块应该很熟悉了,就是下面这样的:

public class Bar {

    static {
       
    }

}

其实,把static关键字去掉,就是Java实例初始化块。编译器会把初始化块复制到每个构造函数中,因此非常适合在多个构造函数中共享代码。

public class Bar {

    private int foo;

    public Bar() {
    }

    public Bar(int bar) {
    }

    {
        try {
            this.foo = Foo.getFoo();
        } catch (Exception e) {
            this.foo = 5;
        }
    }

}

可以看到,既达到了代码复用的目的,还少写了一个函数,可谓一举两得。

0人推荐
随时随地看视频
慕课网APP