java-se - Java:请问这段代码的执行顺序是怎么样的,如果能够详细点更好,谢谢
PHPz
PHPz 2017-04-18 10:36:29
0
2
352
PHPz
PHPz

学习是最好的投资!

reply all(2)
小葫芦

Class variables (static variables) > Static blocks > Constructors > Ordinary member variables > Subclasses except static. All static modifications in JAVA will allocate space at compile time, and objects will only be allocated when used, that is, when new is used, when a subclass inherits a parent class, it obviously needs to be allocated to the parent class first. How can a son come from without a father, right?

迷茫

The subject can help understand the initialization process by decompiling the compiled class file.

Instructions in the command linejavap -l -c -p -v App,执行后就会得到反编译后的内容,下面结合题主给的源码简单分析一下:
下面展示和初始化有关的部分反编译内容
Appclass file

private static com.real.test.App d;
  descriptor: Lcom/real/test/App;
  flags: ACC_PRIVATE, ACC_STATIC

private com.real.test.SubClass t;
  descriptor: Lcom/real/test/SubClass;
  flags: ACC_PRIVATE

static {};
  descriptor: ()V
  flags: ACC_STATIC
  Code:
    stack=2, locals=0, args_size=0
       0: new           #1                  // class com/real/test/App
       3: dup
       4: invokespecial #12                 // Method "<init>":()V  **调用App的构造函数**
       7: putstatic     #15                 // Field d:Lcom/real/test/App;
      10: getstatic     #17                 // Field java/lang/System.out:Ljava/io/PrintStream;
      13: iconst_3   **得到数字常量3**
      14: invokevirtual #23                 // Method java/io/PrintStream.println:(I)V   **打印数字常量3**
      17: return
    LineNumberTable:
      line 4: 0
      line 8: 10
      line 3: 17
    LocalVariableTable:
      Start  Length  Slot  Name   Signature

com.real.test.App();   **构造函数详细内容**
  descriptor: ()V
  flags:
  Code:
    stack=3, locals=1, args_size=1
       0: aload_0
       1: invokespecial #31                 // Method java/lang/Object."<init>":()V   **调用Object的构造函数**
       4: aload_0
       5: new           #32                 // class com/real/test/SubClass
       8: dup
       9: invokespecial #34                 // Method com/real/test/SubClass."<init>":()V   **调用SubClass的构造函数**
      12: putfield      #35                 // Field t:Lcom/real/test/SubClass;
      15: getstatic     #17                 // Field java/lang/System.out:Ljava/io/PrintStream;
      18: iconst_4   **得到数字常量4**
      19: invokevirtual #23                 // Method java/io/PrintStream.println:(I)V   **打印数字常量4**
      22: return
    LineNumberTable:
      line 11: 0
      line 5: 4
      line 12: 15
      line 13: 22
    LocalVariableTable:
      Start  Length  Slot  Name   Signature
          0      23     0  this   Lcom/real/test/App;

public static void main(java.lang.String[]);
  descriptor: ([Ljava/lang/String;)V
  flags: ACC_PUBLIC, ACC_STATIC
  Code:
    stack=2, locals=1, args_size=1
       0: getstatic     #17                 // Field java/lang/System.out:Ljava/io/PrintStream;
       3: ldc           #40                 // String Hello  **得到字符串Hello**
       5: invokevirtual #42                 // Method java/io/PrintStream.println:(Ljava/lang/String   **打印字符串**
       8: return
    LineNumberTable:
      line 16: 0
      line 17: 8
    LocalVariableTable:
      Start  Length  Slot  Name   Signature
          0       9     0  args   [Ljava/lang/String;

SubClassclass file

static {};  **静态块**
  descriptor: ()V
  flags: ACC_STATIC
  Code:
    stack=2, locals=0, args_size=0
       0: getstatic     #8                  // Field java/lang/System.out:Ljava/io/PrintStream;
       3: iconst_1   **得到数字常量1**
       4: invokevirtual #14                 // Method java/io/PrintStream.println:(I)V   **打印数字常量1**
       7: return
    LineNumberTable:
      line 28: 0
      line 26: 7
    LocalVariableTable:
      Start  Length  Slot  Name   Signature

public com.real.test.SubClass();  **构造函数**
  descriptor: ()V
  flags: ACC_PUBLIC
  Code:
    stack=2, locals=1, args_size=1
       0: aload_0
       1: invokespecial #23                 // Method com/real/test/SuperClass."<init>":()V   **调用SuperClass的构造函数**
       4: getstatic     #8                  // Field java/lang/System.out:Ljava/io/PrintStream;
       7: iconst_2   **得到数字常量2**
       8: invokevirtual #14                 // Method java/io/PrintStream.println:(I)V   **打印数字常量2**
      11: return
    LineNumberTable:
      line 31: 0
      line 32: 4
      line 33: 11
    LocalVariableTable:
      Start  Length  Slot  Name   Signature
          0      12     0  this   Lcom/real/test/SubClass;

SuperClassclass file

 com.real.test.SuperClass();
   descriptor: ()V
   flags:
   Code:
     stack=2, locals=1, args_size=1
        0: aload_0
        1: invokespecial #8                  // Method java/lang/Object."<init>":()V   **Object的构造函数**
        4: getstatic     #10                 // Field java/lang/System.out:Ljava/io/PrintStream;
        7: ldc           #16                 // String 构造SuperClass   **得到字符串构造SuperClass**
        9: invokevirtual #18                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V   **打印字符串**
       12: return
     LineNumberTable:
       line 21: 0
       line 22: 4
       line 23: 12
     LocalVariableTable:
       Start  Length  Slot  Name   Signature
           0      13     0  this   Lcom/real/test/SuperClass;

Explain the content roughly (if the subject is interested in JVM instruction set, you can read the JVM specification, which has a very detailed explanation).
The asterisked part in the decompiled content above is the annotation I added. According to the execution order of the code:
1. JVM loads the App class. The static variables in App will be initialized at this time, corresponding to the calling App in the App. Bytecode of constructor
2. Jump to the constructor of App, first initialize the parent class Object, and call Object corresponding to in App Constructor of
3. Initialize the instance variable JVM指令集感兴趣可以看看JVM规范,里面有很详细的解释)。
上面反编译内容中星号部分是我加上的注解。按照代码的执行顺序:
1.JVM加载App类,App中的静态变量在这时会初始化,对应App中调用App的构造函数的字节码
2.跳到App的构造函数,先初始化父类Object,对应App中调用Object的构造函数
3.初始化实例变量SubClass,对应App中调用SubClass的构造函数
4.此时要先加载SubClass类,同时初始化静态变量并执行静态块,对应SubClass中静态块
5.这时执行SubClass中的代码打印出“1”
6.SubClass加载完成后执行构造函数,对应SubClass中构造函数
7.SubClass构造函数最开始是执行SuperClass的构造函数,对应SubClass中调用SuperClass的构造函数
8.执行SuperClass中构造函数中的代码打印出“得到字符串构造SuperClass”
9.SuperClass构造完成return到7中的代码位置,继续执行SubClass剩余的代码
10.执行SubClass中构造函数代码打印出“2”
11.执行完SubClass构造函数return到3中的代码位置,继续执行App剩余的代码
12.执行App中构造函数代码打印出“4”
13.执行完App的构造函数return到1中代码位置,继续初始化的静态变量
14.执行静态块中的方法,答应出“3”
15.进入到main, which corresponds to calling the constructor of SubClass in the App
4. At this time, the

class must be loaded first, and the static variables must be initialized at the same time. Execute the static block, corresponding to static block
in SubClass. 5. At this time, executing the code in

prints out "1"
6. After

is loaded, execute the constructor, corresponding to Constructor
7. The

constructor is initially the constructor that executes

, corresponding to the constructor that calls SuperClass in SubClass
8. Execute the constructor in 🎜 The code in prints out "get string construction SuperClass"
9.🎜The construction is completedreturn to the code position in 7, and continue to execute the remaining code
10. Execute the construction in 🎜 The function code prints out "2"
11. After executing the constructor return to the code position in 3, continue executing the remaining code of App
12. Execute the constructor code in App to print out "4"
13. After executing the constructor of App, return to the code position in 1, Continue to initialize the static variables
14. Execute the method in the static block and print out "3"
15. Enter the main entry method and print out "Hello"🎜 🎜The above process is the rough execution sequence. 🎜 🎜The content of the answer may be a bit confusing. If you don’t understand something, you can ask me. 🎜
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!