Java初始化

Java初始化

Java保证变量在使用前都已经初始化。
对类的成员变量(静态变量和实例变量),在构建类的实例时,首先都会被初始化为一个默认值(数字型变量(int、byte、short、long、float、double)都会被初始化为0,而boolean则是false,char其ascii码也是0,其他非基本类型的变量则会被初始化为null),当然你也可以在定义变量时直接初始化,然后才是由初始化块和构造方法进行初始化。
以下面的例子为依据:



class T {

}

class Test {
    byte b;
    char c;
    short s;
    int i;
    long l;
    float f;
    double d;
    boolean bl;
    T t;

}

public class Main {
    public static void main(String[] args) {
        Test t = new Test();
        System.out.println("byte b is " + t.b);
        System.out.println("char c is [" + (int)t.c + "]");
        System.out.println("short s is " + t.s);
        System.out.println("int i is " + t.i);
        System.out.println("long l is " + t.l);
        System.out.println("float f is " + t.f );
        System.out.println("double d is " + t.d);
        System.out.println("boolean bl is " + t.bl);
        System.out.println("object t is " + t.t);
    }
}

运行结果为:

byte b is 0
char c is [0]
short s is 0
int i is 0
long l is 0
float f is 0.0
double d is 0.0
boolean bl is false
object t is null

静态成员变量也是一样的。
对于本地变量(方法内声明的变量,Java不会提供默认值),如果在使用前没有初始化的话,编译器就会报错(the local variable xx may not have been initialized),通过这种方式就可以保证所有变量在使用前都已被初始化(注:成员变量如果是引用类型,则会被默认初始化为null,上面的例子已经显示了,所以如果引用类型的变量没有显示初始化就直接使用的话,在运行时就会报错(exception-java.lang.NullPointerException))。

初始化顺序

Java的初始化顺序归结下来就下面几条:

当不涉及继承时

  1. 在类第一次被加载时(实例化类的对象或是访问类的静态成员-静态成员变量或是静态方法)初始化类的静态成员变量,当类已经被加载过时静态成员变量不再执行初始化操作(类的静态成员变量只会被初始化一次),静态初始化块(有关键字static和{}组成的代码块)和直接的赋值操作按出现的先后顺序依次进行
  2. 然后实例变量初始化默认值
  3. 执行初始化块和定义变量时的赋值操作,二者的先后顺序和静态成员变量一样,都按照语句出现的先后顺序依次进行
  4. 最后执行构造方法
    下面我们来验证一下上面的5条总结:

class Test {
    Test() {
        System.out.println("***Constructor***");
    }

    static int i = 0;
    static int sk;
    static {
        System.out.println("***default sk is " + sk +"***");
        System.out.println("***static init***");
    }
    static int j  = sf() + i;
    static int sf() {
        System.out.println("***sf()***");
        return 3;
    }
    static {
        System.out.println("***static init***");
    }

    int k;
    {
        System.out.println("***default k is " + k +"***");
        System.out.println("***init instance variable***");
        k = 10;
    }
    int g = k +f();
    int f() {
        System.out.println("***f()***");
        return 3;
    }
    {
        System.out.println("***init instance variable***");
    }


}

public class Main {
        public static void main(String args[]) {
            Test t1 = new Test();
            Test t2 = new Test();
    }
}

结果:

***default sk is 0***
***static init***
***sf()***
***static init***
***default k is 0***
***init instance variable***
***f()***
***init instance variable***
***Constructor***
***default k is 0***
***init instance variable***
***f()***
***init instance variable***
***Constructor***

从上面的结果可以看到首先是静态成员被初始化为默认值,然后执行赋值和静态初始化块(按出现的先后顺序依次执行),再初始化实例成员变量,可以从成员变量k看到变量首先被初始化为默认值0,然后再执行赋值和初始化块(也是按出现的先后顺序依次执行),最后才执行赋值操作。我们还可以看到但第二次实例化Test时,静态成员没有再被初始化了

涉及继承时

1.首先初始化父类的静态成员变量
2.初始化子类的静态成员变量
3.初始化父类的实例成员变量,包括执行初始化块和构造函数
4.最后初始化子类的实例成员变量
下面来验证一下:


class B1 {
    static int sb1 = 3; 
    int ib1;



    B1 () {
        System.out.println("Construct B1");
    }

    {
        ib1 = 5;
        System.out.println("init B1, ib1 is" + ib1);
    }

    static {
        System.out.println("init B1, sb1 is" + sb1);
    }
}

class B2 extends B1 {
    static int sb2 = 3; 
    int ib2;
    {
        ib2 = 5;
        System.out.println("init B2, ib2 is" + ib2);
    }

    static {
        System.out.println("init B2, sb2 is" + sb2);
    }

    B2() {
        System.out.println("Construct B2");
    }
}

class Child extends B2 {
    static int sci = 3; 
    int ic;
    {
        ic = 5;
        System.out.println("init Child, sci  is" + ic);
    }

    static {
        System.out.println("init Child, sci is" + sci);
    }
    Child() {
        System.out.println("Construct Child");
    }
}

public class TTTT {

    public static void main(String[] args) {

         Child c = new Child();
    }
}

结果如下:
init B1, sb1 is3
init B2, sb2 is3
init Child, sci is3
init B1, ib1 is5
Construct B1
init B2, ib2 is5
Construct B2
init Child, sci is5
Construct Child
我们从结果可以看到首先是将B1,B2和Child三个类的静态成员变量初始化后,然后初始化B1的实例成员变量,接着是B2和Child

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值