Java中init和clinit區(qū)別

1 init和clinit區(qū)別

1.1 init和clinit方法執(zhí)行時(shí)機(jī)不同

init是對(duì)象構(gòu)造器方法,也就是說在程序執(zhí)行 new 一個(gè)對(duì)象調(diào)用該對(duì)象類的 constructor 方法時(shí)才會(huì)執(zhí)行init方法
類初始化時(shí)機(jī)
clinit是類構(gòu)造器方法,也就是在jvm進(jìn)行類加載—–驗(yàn)證—-解析—–初始化,中的初始化階段jvm會(huì)調(diào)用clinit方法。

1.2 init和clinit方法執(zhí)行目的不同

  • init是instance實(shí)例構(gòu)造器,對(duì)非靜態(tài)變量解析初始化
  • clinit是class類構(gòu)造器對(duì)靜態(tài)變量,靜態(tài)代碼塊進(jìn)行初始化。
class X {

   static Log log = LogFactory.getLog(); // <clinit>

   private int x = 1;   // <init>

   X(){
      // <init>
   }

   static {
      // <clinit>
   }

}

2 clinit詳解

在準(zhǔn)備階段,變量已經(jīng)賦過一次系統(tǒng)要求的初始值,初始化階段是執(zhí)行類構(gòu)造器<clinit>()方法的過程。

2.1 <clinit>

<clinit>()方法是由編譯器自動(dòng)收集類中的所有類變量的賦值動(dòng)作和靜態(tài)語(yǔ)句塊(static{}塊)中的語(yǔ)句合并產(chǎn)生的

編譯器收集的順序是由語(yǔ)句在源文件中出現(xiàn)的順序所決定的,靜態(tài)語(yǔ)句塊中只能訪問到定義在靜態(tài)語(yǔ)句塊之前的變量,定義在它之后的變量,在前面的靜態(tài)語(yǔ)句塊可以賦值,但是不能訪問如下代碼

public class Test{
static{
i=0;//給變量賦值可以正常編譯通過
System.out.print(i);//這句編譯器會(huì)提示"非法向前引用"
}
static int i=1;
}

2.2 父類的<clinit>

虛擬機(jī)會(huì)保證在子類的<clinit>()方法執(zhí)行之前,父類的<clinit>()方法已經(jīng)執(zhí)行完畢。

public class Test{
static{
i=0;//給變量賦值可以正常編譯通過
System.out.print(i);//這句編譯器會(huì)提示"非法向前引用"
}
static int i=1;
}

因此在虛擬機(jī)中第一個(gè)被執(zhí)行的<clinit>()方法的類肯定是java.lang.Object。

由于父類的<clinit>()方法先執(zhí)行,也就意味著父類中定義的靜態(tài)語(yǔ)句塊要優(yōu)先于子類的變量賦值操作,

如下代碼中,字段B的值將會(huì)是2而不是1。

static class Parent{
    public static int A=1;
    static{
    A=2;}
    static class Sub extends Parent{
    public static int B=A;
    }
    public static void main(String[]args){
    System.out.println(Sub.B);
    }
}

2.3 接口

接口中不能使用靜態(tài)語(yǔ)句塊,但仍然有變量初始化的賦值操作,因此接口與類一樣都會(huì)生成<clinit>()方法。

但接口與類不同的是,執(zhí)行接口的<clinit>()方法不需要先執(zhí)行父接口的<clinit>()方法。

只有當(dāng)父接口中定義的變量使用時(shí),父接口才會(huì)初始化。 另外,接口的實(shí)現(xiàn)類在初始化時(shí)也一樣不會(huì)執(zhí)行接口的<clinit>()方法。

接口中的屬性都是static final類型的常量,因此在準(zhǔn)備階段就已經(jīng)初始化話

參考

深入理解jvm--Java中init和clinit區(qū)別完全解析

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 原文出處 init和clinit區(qū)別 ①init和clinit方法執(zhí)行時(shí)機(jī)不同 init是對(duì)象構(gòu)造器方法,也就是說...
    sambillyr閱讀 2,305評(píng)論 1 2
  • Java中 和<clinit>區(qū)別 和<clinit>方法執(zhí)行時(shí)機(jī)不同 是對(duì)象構(gòu)造器方法,也就是說在程序執(zhí)行 ne...
    liuzx32閱讀 758評(píng)論 0 0
  • 一、初始化初識(shí) 1. 初始化是什么 Java語(yǔ)言規(guī)范中了Java有兩種數(shù)據(jù)類型:簡(jiǎn)單類型和引用類型。 簡(jiǎn)單類型包括...
    HRocky閱讀 609評(píng)論 0 1
  • Java虛擬機(jī)整體篇幅如下: Java虛擬機(jī)基礎(chǔ)——1Java的內(nèi)存模型Java虛擬機(jī)基礎(chǔ)——2JVM運(yùn)行時(shí)數(shù)據(jù)區(qū)...
    隔壁老李頭閱讀 2,945評(píng)論 1 16
  • 代碼編譯的結(jié)果從本地機(jī)器碼轉(zhuǎn)變?yōu)樽止?jié)碼,是存儲(chǔ)格式發(fā)展的一小步,確實(shí)編譯語(yǔ)言發(fā)展的一大步。 虛擬機(jī)把描述類的數(shù)據(jù)從...
    胡二囧閱讀 1,052評(píng)論 0 0

友情鏈接更多精彩內(nèi)容