Java静态变量和静态代码块之间的执行顺序比较有意思,这里尽量考虑可能出现的情况,总结如下:
- 静态变量和静态代码块的执行顺序由这些静态变量和静态代码块出现的顺序决定
- 在静态代码块里使用在该静态代码块后面定义的静态变量时,只能引用静态变量或使用静态变量赋值表示式,但是赋值表达式仅在定义该静态变量没有赋值的情况下生效,其余情况都不会生效,在静态代码块里通过其他任何方式调用后面定义的静态变量都无法编译
- 在静态代码块里使用未声明的静态变量(不论在该静态代码块前还是后声明)都无法编译
实际上,上述第二点的本质是给静态变量初始化,可以通过反编译class文件验证这点。
// 源码:STR_AFTER_CODE未初始化
public class StaticValid {
private static String STR_BEFORE_CODE = "在静态代码块前面的变量";
static {
System.out.println(STR_BEFORE_CODE);
STR_AFTER_CODE = "asads";
}
private static String STR_AFTER_CODE; // STR_AFTER_CODE没有初始化
public static void main(String[] args) {
System.out.println("---------");
System.out.println(STR_AFTER_CODE);
System.out.println("---------");
}
}
反编译上面的代码(如下),可以发现静态代码块里的STR_AFTER_CODE
赋值语句实际上是在定义该静态变量时执行了。
import java.io.PrintStream;
public class StaticValid
{
private static String STR_BEFORE_CODE = "在静态代码块前面的变量";
static
{
System.out.println(STR_BEFORE_CODE);
}
private static String STR_AFTER_CODE = "asads";
public static void main(String[] args)
{
System.out.println("---------");
System.out.println(STR_AFTER_CODE);
System.out.println("---------");
}
}
如果STR_AFTER_CODE
初始化了呢,下面来看看:
// 源码:STR_AFTER_CODE初始化了
public class StaticValid {
private static String STR_BEFORE_CODE = "在静态代码块前面的变量";
static {
System.out.println(STR_BEFORE_CODE);
STR_AFTER_CODE = "asads";
}
private static String STR_AFTER_CODE = "在静态代码块后面的变量"; // STR_AFTER_CODE初始化了
public static void main(String[] args) {
System.out.println("---------");
System.out.println(STR_AFTER_CODE);
System.out.println("---------");
}
}
// Output:
// 在静态代码块前面的变量
// ---------
// 在静态代码块后面的变量
// ---------
反编译上面的代码如下,发现这里static
代码块里的赋值语句还在,但是结合上面代码的输出,发现赋值语句看起来并没有生效,这是因为后面赋值为"在静态代码块后面的变量"
为第二次赋值,这也验证了第一点。除此之外,如果此时在static
里提前使用了STR_AFTER_CODE
会无法编译。
import java.io.PrintStream;
public class StaticValid
{
private static String STR_BEFORE_CODE = "在静态代码块前面的变量";
static
{
System.out.println(STR_BEFORE_CODE);
STR_AFTER_CODE = "asads";
}
private static String STR_AFTER_CODE = "在静态代码块后面的变量";
public static void main(String[] args)
{
System.out.println("---------");
System.out.println(STR_AFTER_CODE);
System.out.println("---------");
}
}