static代码块非必执行

public class TestA {
    static String a = "aaa";
    static {
        System.out.println("****** static_TestA ******");
    }
}

public class TestB {
    static final String b = "bbb";
    static {
        System.out.println("****** static_TestB ******");
    }
}

public class Test {
    public static void main(String[] args) {
        System.out.println(TestA.a);
        System.out.println("======分割线======");
        System.out.println(TestB.b);
    }
}

打印结果:

****** static_TestA ******
aaa
======分割线======
bbb

Process finished with exit code 0

TestB 的 static 代码块并未执行

原因如下:

TestA  的字节码文件:

public class com/lpy/bigdata/TestA {

  // compiled from: TestA.java

  // access flags 0x8
  static Ljava/lang/String; a

  ...
  ...

  // access flags 0x8
  static <clinit>()V
   L0
    LINENUMBER 4 L0
    LDC "aaa"
    PUTSTATIC com/lpy/bigdata/TestA.a : Ljava/lang/String;
   L1
    LINENUMBER 6 L1
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    LDC "****** static_TestA ******"
    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
   L2
    LINENUMBER 7 L2
    RETURN
    MAXSTACK = 2
    MAXLOCALS = 0
}

       虽然代码在开始就给变量 a 赋了值:static String a = "aaa"; 但在执行字节码文件时,一开始并未给 a 赋值,而是在 static 代码块里进行赋值,自然就执行了 static 代码块。

TestB  的字节码文件:

public class com/lpy/bigdata/TestB {

  // compiled from: TestB.java

  // access flags 0x18
  final static Ljava/lang/String; b = "bbb"

  // access flags 0x1
  public <init>()V
   L0
    LINENUMBER 3 L0
    ALOAD 0
    INVOKESPECIAL java/lang/Object.<init> ()V
    RETURN
   L1
    LOCALVARIABLE this Lcom/lpy/bigdata/TestB; L0 L1 0
    MAXSTACK = 1
    MAXLOCALS = 1

  // access flags 0x8
  static <clinit>()V
   L0
    LINENUMBER 6 L0
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    LDC "****** static_TestB ******"
    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
   L1
    LINENUMBER 7 L1
    RETURN
    MAXSTACK = 2
    MAXLOCALS = 0
}

       TestB 的 b 也在一开始就赋了值:bbb,不同的是TestB 的 b 用 final 修饰,由 TestB 的字节码文件得知,常量的赋值就真的在最开始赋值的地方赋了值,那么在 Test 里打印 TestB.b 的值时,由于直接就拿到了 b 的值,因此就没必要再走 TestB 的 static 代码块了。

       但是如果执行过一次 main 方法之后,再把 TestA 里的 a 加上 final ,它依然会执行 TestA 的 static 代码块,这是由于 java 文件编译过后,再次执行时系统会进行优化导致的。

猜你喜欢

转载自blog.csdn.net/S_Alics/article/details/106127479