簡單說說和
阿新 • • 發佈:2019-01-27
<clinit>:在初始化時執行,從上到下的收集有初始值的靜態成員域或static塊的值,進行賦值,執行本類的<clinit>函式時,父類的<clinit>函式已經執行完畢,若本類不具有靜態成員域或static塊,則JVM不會為該類產生<clinit>函式。
<init>:其實就是建構函式,在生成class檔案時,編譯器會在建構函式中新增一些程式碼,在本類的建構函式中,會最優先呼叫父類的<init>函式,接著執行剩餘建構函式中剩餘的程式碼,我們來看看下面的程式碼:
class deal0 { } class deal extends deal0 { int n; int m=2; deal() { n=1; } } public class Try { public static void main(String[] args) { deal x=new deal(); } }
反編譯deal.class檔案:
建構函式的位元組碼解釋請看註釋,可以看到<init>先呼叫父類的<init>函式,接著初始化具有初始值的變數(實測後,初始化順序為程式碼中由上到下的出現順序),然後在執行我們自己寫的程式碼。Last modified 2018-1-31; size 240 bytes MD5 checksum 8b1b2a8d7345905b383f50f5fd6d2a2a Compiled from "Try.java" class deal extends deal0 minor version: 0 major version: 52 flags: ACC_SUPER Constant pool: #1 = Methodref #5.#15 // deal0."<init>":()V #2 = Fieldref #4.#16 // deal.m:I #3 = Fieldref #4.#17 // deal.n:I #4 = Class #18 // deal #5 = Class #19 // deal0 #6 = Utf8 n #7 = Utf8 I #8 = Utf8 m #9 = Utf8 <init> #10 = Utf8 ()V #11 = Utf8 Code #12 = Utf8 LineNumberTable #13 = Utf8 SourceFile #14 = Utf8 Try.java #15 = NameAndType #9:#10 // "<init>":()V #16 = NameAndType #8:#7 // m:I #17 = NameAndType #6:#7 // n:I #18 = Utf8 deal #19 = Utf8 deal0 { int n; descriptor: I flags: int m; descriptor: I flags: deal(); descriptor: ()V flags: Code: stack=2, locals=1, args_size=1 0: aload_0 //將this指標壓入運算元棧 1: invokespecial #1 //Method deal0."<init>":()V,此處呼叫父類的建構函式,父類建構函式的執行結果寫入到this指標所指的記憶體處 4: aload_0 //將this指標壓入運算元棧 5: iconst_2 //將常量池中2壓入運算元棧 6: putfield #2 // Field m:I,使記憶體中m的值為2,此時會用到運算元棧中的this指標,來找到例項物件在堆記憶體中的位置。 9: aload_0 //將this指標壓入運算元棧 10: iconst_1 //將常量池中的1壓入運算元棧,this指標作用同上 11: putfield #3 // Field n:I,給記憶體中的n賦予1 14: return LineNumberTable: line 10: 0 line 8: 4 line 11: 9 line 12: 14 } SourceFile: "Try.java"