关于类加载的时候,static代码块中可以赋值但不能引用的问题
类加载过程:
先看代码:
class StaticTest{
static {
a=10;
System.out.println(a);//报错:Illegal forward reference
}
static int a=1;
public static void main(String[] args) {
StaticTest staticTest = new StaticTest();
}
}
编译不通过,报错信息说非法的前向引用
,因为对于a的声明在下面的静态变量中,属于语法错误,jvm编译不通过。
如果去掉输出这句,变成下面的代码:
class StaticTest{
static {
a=10;
}
static int a=1;
public static void main(String[] args) {
StaticTest staticTest = new StaticTest();
System.out.println(a);
}
}
输出结果为:1
问题:为什么a还没有被声明就可以被赋值,为什么不报错?
答:
1.类加载的时候在连接
阶段的准备
中,做了下面的事情:
为类的静态变量
分配内存
并设置默认初始值
,这些变量所使用的内存都将在方法区
中进行分配。
注意:
这时候进行内存分配的仅包括类变量(static),而不包括实例变量,实例变量会在对象实例化的时候随对象一起分配到堆中。
这些内存都将在方法区中分配
非常量(final)的静态数据类型被默认赋对应类型的零值(如0、0L、null、false等),而不是程序中显示的赋值。
准备阶段检测到了a
为int
,分配内存并为a
赋初值0
。
2.然后进入初始化阶段之后,对静态代码块执行初始化,静态变量显示初始化。
初始化的顺序为代码排列顺序
。如静态代码块在静态变量声明前,静态变量a在静态代码块和静态变量中分别做了赋值,则a先被静态代码块赋值,后被静态变量赋值语句赋值。并且静态语句块只能访问到定义在静态语句块之前的变量,定义在它之后的变量,在前面的静态语句块可以赋值,但是不能访问
。
所以说初始化之前a=0
,先执行static代码块,a=10
;然后执行静态变量,a=1
;