2013-04-12 93 views
1

我有如下场景 package com.example.test;执行顺序,静态块

public class StaticTest { 

    public static final String STATIC_VAR="Static Var"; 

    static{ 
     System.out.println("Static Block Called...."); 
    } 
public static void init(){} 
} 

package com.example.test; 

public class MainClass { 
    public static void main(String[] args) { 
     System.out.println("Test static initialization"); 
     String staticvar =StaticTest.STATIC_VAR; 
     System.out.println("Referred static variable--> "+ staticvar); 
     System.out.println("Calling static method"); 
     StaticTest.init(); 
     System.out.println("Static method invoked"); 
    } 

} 

我得到的输出是

Test static initialization 
Referred static variable--> Static Var 
Calling static method 
**Static Block Called....** 
Static method invoked 

和输出我所期待的是

Test static initialization 
**Static Block Called....** 
Referred static variable--> Static Var 
Calling static method 
Static method invoked 

我想,只要我指静态变量静态块将得到执行。

有什么解释?

+1

请参阅[Java静态类初始化](http://stackoverflow.com/questions/3499214/java-static-class-initialization)和[静态块和静态变量在一个类中执行的顺序是什么?](http ://stackoverflow.com/questions/12448465/in-what-order-are-static-blocks-and-static-variables-in-a-class-executed)。 –

回答

0

主要原因是您将STATIC_VAR声明为常量值,该值将由编译器内联,而不是被引用。将代码更改为

public static /*final*/ String STATIC_VAR="Static Var"; 

并且您将获得您期望的行为。

参见Java语言规范的§12.4.1. When Initialization Occurs

类或接口类型T将紧接在以下中的任何一个的第一次出现之前被初始化:

  • ...
  • 使用由T声明的静态字段,该字段为而非常量变量(第4.12.4节)。

参见为技术背景的常量值inlining其他的答案。

3
String staticvar =StaticTest.STATIC_VAR; 

不加载类StaticTest。相反,编译器内嵌的常数为MainClass。因此,在运行时,该代码将被执行:

String staticvar = "Static Var"; 

的JLS调用此一“constant”:

原始类型或String类型的变量,也就是最后的和与编译初始化 时间常量表达式(§15.28),被称为常量变量 。

这意味着StaticTest.init();是VM第一次实际加载类。这会导致静态块的执行。

3

因为变量是public static final它被编译器内联。

所有对它的引用都被替换为实际值,因为它不能改变,这就是所谓的编译时间常量。

public static final String STATIC_VAR=getStaticVar(); 
private static String getStaticVar() { 
    return "Static Var"; 
} 

你会得到你所期望的结果 - 如果你的值赋给一个方法的返回值

System.out.println("Test static initialization"); 
String staticvar = "Static Var"; 

您的代码基本上被编译成。

有一个good SO answer解释内联和由JLS给出的编译时间常量的保证。