Java中的静态块没有执行

class Test{ public static void main(String arg[]){ System.out.println("**MAIN METHOD"); System.out.println(Mno.VAL);//SOP(9090); System.out.println(Mno.VAL+100);//SOP(9190); } } class Mno{ final static int VAL=9090; static{ System.out.println("**STATIC BLOCK OF Mno\t:"+VAL); } } 

我知道一个static块加载类时执行。 但是在这种情况下,类Mno的实例variables是final ,因为static块没有执行。

为什么? 如果我将删除final ,它会工作正常吗?

哪个内存将被首先分配, static finalvariables还是static块?

如果由于final访问修饰符类没有得到加载,那么variables如何获得内存?

  1. 一个static final int字段是一个编译时常量 ,它的值被硬编码到目标类中,而不参考它的原点;
  2. 因此你的主类不会触发包含该字段的类的加载;
  3. 因此该类中的静态初始化程序不会被执行。

在具体的细节上,编译的字节码对应于这个:

 public static void main(String arg[]){ System.out.println("**MAIN METHOD"); System.out.println(9090) System.out.println(9190) } 

只要删除final ,它不再是编译时常量,上面描述的特殊行为不适用。 Mno类按照您的预期进行加载,并执行其静态初始化程序。

该类未被加载的原因是VALfinal 并且用常量expression式 (9090)进行初始化。 当且仅当满足这两个条件时,才在编译时评估常量,并在需要时进行“硬编码”。

为了防止在编译时评估expression式(并使JVM加载你的类),你可以:

  • 删除最后的关键字:

     static int VAL = 9090; //not a constant variable any more 
  • 或者将右边的expression式改为非常量(即使variables仍然是最终的):

     final static int VAL = getInt(); //not a constant expression any more static int getInt() { return 9090; } 

如果你看到使用javap -v Test.class生成的字节码,main()就会出现:

 public static void main(java.lang.String[]) throws java.lang.Exception; flags: ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=1, args_size=1 0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #3 // String **MAIN METHOD 5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 8: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream; 11: sipush 9090 14: invokevirtual #5 // Method java/io/PrintStream.println:(I)V 17: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream; 20: sipush 9190 23: invokevirtual #5 // Method java/io/PrintStream.println:(I)V 26: return 

你可以清楚地看到在“ 11: sipush 9090 ”中直接使用了静态的最终值,因为Mno.VAL是一个编译时间常量。 因此不需要加载Mno类。 因此,Mno的静态块不被执行。

您可以通过手动加载Mno来执行静态块,如下所示:

 class Test{ public static void main(String arg[]) throws Exception { System.out.println("**MAIN METHOD"); Class.forName("Mno"); // Load Mno System.out.println(Mno.VAL); System.out.println(Mno.VAL+100); } } class Mno{ final static int VAL=9090; static{ System.out.println("**STATIC BLOCK OF Mno\t:"+VAL); } } 

1)实际上你没有扩展那个Mno类,所以当编译开始时,它会产生variablesVAL的常量,当执行开始时,该variables是需要加载它从memory.so它不需要你的类的引用,使静态程序块不执行。

2)如果一个类扩展了那个Mno类,那么这个静态块被包含在A类中的话,那么这个静态块就被执行了。 例如.. public class A extends Mno {

 public static void main(String arg[]){ System.out.println("**MAIN METHOD"); System.out.println(Mno.VAL);//SOP(9090); System.out.println(Mno.VAL+100);//SOP(9190); } } class Mno{ final static int VAL=9090; static`{` System.out.println("**STATIC BLOCK OF Mno\t:"+VAL); } } 

据我所知,它将按照外观顺序执行。 例如 :

  public class Statique { public static final String value1 = init1(); static { System.out.println("trace middle"); } public static final String value2 = init2(); public static String init1() { System.out.println("trace init1"); return "1"; } public static String init2() { System.out.println("trace init2"); return "2"; } } 

将打印

  trace init1 trace middle trace init2 

我刚刚testing过,静态被初始化(=>打印),当“Statique”类被实际使用并且在另一段代码中“执行”时(我的例子是“新Statique()”)。