关于Java类中变量的初始化


public class Test {
    int a;
    static int b = 123;
    final static int c;
    void init(){
        int d;
    }

    public static void main(String[] args) {
        int e;
        System.out.println(e);
    }
}

上面的Test类中定义了5个不同类型的变量,那么这些变量是如何进行初始化的呢?要先声明一点,上述代码是有问题的,编译不通过。

首先给大家明确一下Java中关于变量的类型,Java有三种变量类型,类变量,实例变量,局部变量。局部变量的生命周期与声明局部变量方法的声明周期相同,仅当方法被调用时,创建局部变量,方法执行结束,销毁局部变量。

类变量的初始化分为两个阶段。第一次是在类加载的准备阶段。准备阶段会正式为类变量分配内存并设置类变量的初始值。如果类变量是基本数据类型,初始值为其对应初值,如果为对象类型,初始值为null,执行下面代码,结果为null,0

public class Test {
    static Integer b;
    static int c;
    
    public static void main(String[] args) {
        System.out.println(b+","+c);
    }
}

准备阶段还有一种例外情况,如果类变量同时被final关键字修饰,那么准备阶段就会直接将变量赋值。下面代码中,c的值会在准备阶段直接赋值为123。

public class Test {
    final static int c = 123;
    public static void main(String[] args) {
        System.out.println(c);
    }
}

对于没有被final关键字修饰的类变量,其赋值过程是在类加载过程中的初始化阶段。实例变量则会在对象实例化时随着对象一起被分配在Java堆中。而类变量随类加载过程中被分配给堆上的逻辑划分——方法区。

回到文章最开头的例子,实例变量a和类变量b的分配初始化如上所述,常量c在准备阶段会被直接赋值,而此处并没有对c赋值,故编译报错。局部变量d随着方法init的调用在栈上分配,局部变量e的定义没有问题,但未赋值的局部变量无法被访问。

其实这里有个小细节,一个局部变量如果创建后从未被使用过,编译器会自动优化忽略掉这个变量的定义,具体可查看编译后的class文件。

你可能感兴趣的:(Java,JVM)