雞與蛋問題(先有Class還是先有Object)
轉自知乎:https://www.zhihu.com/question/30301819
簡短答案:“雞・蛋”問題通常都是通過一種叫“自舉”(bootstrap)的過程來解決的。
其實“雞蛋問題”的根本矛盾就在於假定了“雞”或“蛋”的其中一個要先進入“完全可用”的狀態。而許多現實中被簡化為“雞蛋問題”的情況實際可以在“混沌”中把“雞”和“蛋”都初始化好,而不存在先後問題;在它們初始化的過程中,兩者都不處於“完全可用”狀態,而完成初始化後它們就同時都進入了可用狀態。
打個比方,番茄炒蛋。並不是要先把番茄完全炒好,然後把雞蛋完全炒好,然後把它們混起來;而是先炒番茄炒到半熟,再炒雞蛋炒到半熟,然後把兩個半熟的部分混在一起同時炒熟。
java.lang.Object是一個Java類,但並不是java.lang.Class的一個例項。後者只是一個用於描述Java類與介面的、用於支援反射操作的型別。這點上Java跟其它一些更純粹的面嚮物件語言(例如Python和Ruby)不同。
而第2個假設是對的:java.lang.Class是java.lang.Object的派生類,前者繼承自後者。
雖然第1個假設不對,但“雞蛋問題”仍然存在:在一個已經啟動完畢、可以使用的Java物件系統裡,必須要有一個java.lang.Class例項對應java.lang.Object這個類;而java.lang.Class是java.lang.Object的派生類
事實是:這些相互依賴的核心型別完全可以在“混沌”中一口氣都初始化好,然後物件系統的狀態才叫做完成了“bootstrap”,後面就可以按照Java物件系統的一般規則去執行。JVM、JavaScript、Python、Ruby等的執行時都有這樣的bootstrap過程。
在“混沌”(boostrap過程)裡,
JVM可以為物件系統中最重要的一些核心型別先分配好記憶體空間,讓它們進入[已分配空間]但[尚未完全初始化]狀態。此時這些物件雖然已經分配了空間,但因為狀態還不完整所以尚不可使用。
然後,通過這些分配好的空間把這些核心型別之間的引用關係串好。到此為止所有動作都由JVM完成,尚未執行任何Java位元組碼。
然後這些核心型別就進入了[完全初始化]狀態,物件系統就可以開始自我執行下去,也就是可以開始執行Java位元組碼來進一步完成Java系統的初始化了。
總而言之:番茄炒蛋,在混沌中一口氣初始化完成,稱為完成了“bootstrap”。