我在网上查了很多资料都是说:java中static变量的初始化要在static块的之前执行,并且这个网页http://blog.csdn.net/ice_kane/archive/2010/01/15/5194168.aspx给出了代码证明。但是我自己写的代码却说明static变量和static块的执行顺序取决于他们在类中的声明顺序,我的代码如下:public class StaticTest {
static{//静态块在静态变量之前声明
a=100;
} public static int a=10; public static void main(String[] args) {
System.out.println(StaticTest.a);//这里打印出的是10,说明public static int a=10;在static块之后 执行
}
}public class StaticTest {
public static int a=10;//静态变量在静态块之前声明 static{
a=100;
} public static void main(String[] args) {
System.out.println(StaticTest.a);//这里打印出的是100,说明static块在public static int a=10之后执行
}
}如果按照静态变量先于static块初始化的理论,两个程序打印出来的应当都是100啊,我就不明白了
我也不知道我说清了没有
static{//静态块在静态变量之前声明
a=100;
} public static int a=10; public static void main(String[] args) {
System.out.println(StaticTest.a);//这里打印出的是10,说明public static int a=10;在static块之后 执行
}
}public class StaticTest {
public static int a=10;//静态变量在静态块之前声明 static{
a=100;
} public static void main(String[] args) {
System.out.println(StaticTest.a);//这里打印出的是100,说明static块在public static int a=10之后执行
}
}如果按照静态变量先于static块初始化的理论,两个程序打印出来的应当都是100啊,我就不明白了
我也不知道我说清了没有
public class StaticTest {
static{
System.out.println(a);//出现“非法先前引用”
}
public static int a=10;
public static void main(String[] args) {
System.out.println(StaticTest.a);
}
}而下面这个代码不会出现
public class StaticTest {
static{
a=20;//这个不会出现“非法先前引用”
}
public static int a=10;
public static void main(String[] args) {
System.out.println(StaticTest.a);
}
}
真是挺奇怪的
static {
a = 100;
System.out.println(a);
}这样是没问题的
http://blog.csdn.net/ice_kane/archive/2010/01/15/5194168.aspx那么对于静态变量和静态初始化块之间、变量和初始化块之间的先后顺序又是怎样呢?是否静态变量总是先于静态初始化块,变量总是先于初始化块就被初始化了呢?实际上这取决于它们在类中出现的先后顺序。
public class StaticTest {
static{//静态块在静态变量之前声明
a=100;
}
public static int a=10; public static void main(String[] args) {
System.out.println(StaticTest.a);//这里打印出的是10,说明public static int a=10;在static块之后 执行
}
}一个类在你用之前有“装载,链接,初始化”这么几个阶段,链接又有“验证,准备,解析”这三个阶段。
装载就是把2进制的class文件加载到JVM。
链接就是分配内存,将符号引用解析为直接引用还有给变量赋默认值。(静态变量[类变量]就是在这个阶段创建的)
初始化就是执行初始化语句和初始化块。初始化顺序为(见The Java Language Specification§12.4.2):
<fieldset>
9. Next, execute either the class variable initializers and static initializers of the class, or the field initializers of the interface, in textual order, as though they
were a single block, except that final class variables and fields of interfaces
whose values are compile-time constants are initialized first (§8.3.2.1, §9.3.1,
§13.4.9).
</fieldset>
好,再看你的代码:
public static int a
a这个变量是在准备阶段创建的(链接的第二个阶段),创建玩并给了默认值0,int变量的默认值为0.然后到类的初始化阶段按照文本中出现的先后顺序进行初始化。先执行static块中的,初始化为100,然后再执行你声明时的显示初始化 a=10,最后a的值为10.所以在main中打印的结果就位10了。再看你的第二个疑问,为什么会有“非法先前引用”的问题。先看The Java Language Specification§8.3.2.3的描述:
<fieldSet>
The declaration of a member needs to appear textually before it is used only if
the member is an instance (respectively static) field of a class or interface C and
all of the following conditions hold:
• The usage occurs in an instance (respectively static) variable initializer of C
or in an instance (respectively static) initializer of C.
• The usage is not on the left hand side of an assignment.
• The usage is via a simple name.
• C is the innermost class or interface enclosing the usage.
</fieldset>
就是说 如果以下四种情况全部满足,那么类C的成员要在用之前声明:(大概翻译下,不是很准确)
1·在(实例/静态)变量初始化器中或者(实例/静态)初始化器中使用
2·使用时不在赋值语句的左边
3·通过简单名词使用
4·C是一个最内部的类但是在外部的类中使用
public class StaticTest {
static{
System.out.println(a);//static块中使用a符合上述情况,要在使用前声明,所以出现了一个error。
// 如果改为System.out.println(StaticTest.a)就不会报错了。(不符合第3点,没使用简单名称a,而用了StaticTest.a)
}
public static int a=10;
public static void main(String[] args) {
System.out.println(StaticTest.a);
}
}public class StaticTest {
static{
a=20;//这个a在赋值语句的左边,不符合第2点。所以是可以的。
}
public static int a=10;
public static void main(String[] args) {
System.out.println(StaticTest.a);
}
}
static{
System.out.println(a);//出现“非法先前引用”
}
public static int a=10;
public static void main(String[] args) {
System.out.println(StaticTest.a);
}
}
你这边a不是还没有声明,就直接使用它的引用了,当然是非法引用了
public class StaticTest {
static{
a=20;//这个不会出现“非法先前引用”
System.out.println(a);//这里为什么会出现“非法先前引用”?}
public static int a=10;
public static void main(String[] args) {
System.out.println(StaticTest.a);
}
}
a的声明在静态块之后,但是为什么静态块中a=20;不会出现“非法向前引用”,而System.out.println(a);会出现“非法向前引用”?
public class StaticTest {
static {
a = 100;
} public static int a;
public static void main(String[] args) {
System.out.println(StaticTest.a);
}
}这个运行结果是100,而不是0,说明顺序是这样的,首先创建static的字段,并初始化为0,然后按顺序执行static的赋值语句