日期:2014-05-20  浏览次数:20668 次

类加载以及类初始化问题
正确代码如下:
Java code

public class StaticClass{
    static{
        a = 1;
        System.out.println("-----------------");
    }
    public static int a = 10;

}


错误代码如下:
Java code

public class StaticClass{
    static{
        a = 1;
        System.out.println("-----------------"+a);
    }
    public static int a = 10;

}


问什么静态块里可以赋值不可以引用?

------解决方案--------------------
本质上是可以的,只不过javac这个编译器做出了限制

假设编译可以通过,类初始化做了什么?

先为a分配内存,赋默认值0

然后将a赋值为1

再将a赋值为10

javac或许是因为觉得这个赋值顺序会导致混乱,干脆禁止通过编译
------解决方案--------------------
根据JVM的spec的一部分定义“The static initializers and class variable initializers are executed in textual order. They may not refer to class variables declared in the class whose declarations appear textually after the use, even though these class variables are in scope. This restriction is designed to catch, at compile time, most circular or otherwise malformed initializations.”可以看出

类变量的初始化顺序是按照它们出现在代码中的顺序来的,而且是不可以在它们定义之前来引用。 这个限制是为了在编译器抓住那些怪异的初始化过程。就是这个例子提到的。

那为什么可以赋值,却不能在输出中出现呢? 赋值是putstatic操作,引用是getstatic操作,我个人理解是编译器只会认为getstatic操作是一个引用,所以就编译错。而且如果去掉编译器的这个限制的话,我认为这种写法也是可以执行的。

你可以把a=1的赋值语句替换成a++就可以看到a++这一句是编译错的,因为a=1是一个简单的putstatic操作,但是a++则包含了一个getstatic的操作。
------解决方案--------------------
是jvm字节码指令,一个是为静态变量赋值-压栈,一个是获取静态变量值-出栈