2017-08-09 177 views
0

我想了解一個類加載並初始化時的確切場景。我看到下面的兩篇文章給出不同的答案類加載和初始化

javarevisited - A類類是用在Java中創建whenan實例的初始化無論()關鍵字或使用反射使用Class.forName(),這可能拋出Java中的ClassNotFoundException。

Java world-那麼,什麼時候分類加載?有兩種情況:執行新的字節碼時(例如,FooClass f = 新的 FooClass();)以及字節碼對類(例如System.out)進行靜態引用時的情況。

所以當我使用new關鍵字創建一個類的實例是類加載或初始化?


另一件事要問關於裝載由於引用變量:

javarevisited - 類加載是由類加載器中的Java可以實現儘快急切地加載類爲其他類引用完成,或延遲加載類,直到需要類的初始化發生

是什麼筆者通過參考這裏是什麼意思?他是否暗示如果A類具有B類的引用變量,那麼B類在其引用在A中遇到時會被加載?

但筆者下面說類NOTUSED不加載,但我看到有ClassInitializationTest類的參考

javarevisited -

/** * 這是不是在這個程序中使用的Java類,因此不是由JVM */

class NotUsed { 
static { System.out.println("NotUsed Class is initialized "); } 

}

加載3210
+0

通過閱讀文章,javaworld文章更加簡單化,並提供了高層次的概述,而javarevisited文章更多地涉及細節,因此它們不完全相互矛盾,只是談論不同的事情。至於你的參考問題,是的,這就是它的意思。 – Oleg

回答

1

你對javaworld文章感到困惑。雖然這有點苛刻,但爲了這個答案的目的,我們只是說它是錯誤的,而忽略它。

jvm specification

Java虛擬機動態加載,鏈接和初始化類和接口。 加載是找到具有特定名稱的類或接口類型的二進制表示並從該二進制表示創建類或接口的過程。鏈接是取類或接口並將其組合到Java虛擬機的運行時狀態以使其可以執行的過程。 初始化類或接口包括執行類或接口的初始化方法

從高亮顯示的文本上面可以看到什麼加載和初始化意味着和和javaworld使用裝載(錯誤地)作爲他們的綜合條款。

jls

12.4.1。當初始化時發生

類或接口類型T將在以下中的任何一個的所述第一發生之前​​立即初始化:

  • T是一個類並且創建T的實例。
  • 調用由T聲明的靜態方法。
  • 指定由T聲明的靜態字段。
  • 使用由T聲明的靜態字段,該字段不是常量變量(§4.12.4)。
  • T是頂級類(第7.6節),執行了在T(§8.1.3)中詞彙嵌套的斷言語句(第14.10節)。

從javarevisited文章:

NotUsed o = null; 
.. 
class NotUsed { 
    static { System.out.println("NotUsed Class is initialized"); } 
} 

聲明一個變量沒有列爲導致初始化,所以它沒有初始化的"NotUsed Class is initialized"不會被打印出來的事情之一。如果NotUsed將被加載,使用sun的java 8上的默認ClassLoader它不會被加載,所以它不是由規範定義的。

+0

謝謝@Oleg。作者說:「類加載是通過Java中的類加載器來完成的,一旦另一個類引用它就可以實現加載類,但後來在NotUsed方法的註釋中看到」/ ** * Java類,它是未在此程序中使用,因此未由JVM加載* /「但有 」NotUsed o = null;「 ClassInitializationTest類中的引用語句 –

+0

只是一個簡單的例子:考慮我們引用Fizz類。哪個語句導致類加載。我相信(2)會導致Fizz類的使用(加載後)。但是聲明(1)是否會導致類加載?Fizz fizz = null; ------------(1) fizz = new Fizz(); ----------(2)。 –

+1

@SreemanthJasti他的意思是規範沒有定義要做什麼,它可以以任何方式實現。我只是檢查了標準的Java 8,他是正確的,它不會被加載。你可以基於[這個答案](https://stackoverflow.com/a/482909/1398418)自己玩。在你的例子中(1)什麼都不會發生,但理論上它可以被加載但是不會被初始化(jls禁止它)。 (2)實際上,默認的類加載器會被加載並初始化,理論上它可能已經被加載過。 – Oleg

-1
myClass a = new myClass(); 

正如我所教導的,第一部分是初始化,第二部分是「=」後的加載。

您可以初始化類:

myClass a; 

然後在後面的代碼上加載:

a = new myClass(); 

同爲變量初始化。

+0

這是不相關的,他問** **類**加載。正如類加載器所做的一樣。 – Oleg