2013-05-02 19 views
4

在下列情況下,何時在java中加載導入的類?

import A; 
public class B{ 
    static A a; 
    static{ 
     a = new A(); 
    } 
} 

難道之前正確初始化astatic initialization block被調用?注意:這裏是A日誌框架。

+2

通過初始化'A'(A類或您創建的'A'實例),你是什麼意思?該靜態塊不會被執行,直到某些事件觸發加載類「B」。 – 2013-05-02 04:36:18

+0

對不起。修正問題 – nikel 2013-05-02 04:40:12

回答

4

在上面提到的情況下,靜態塊將在A初始化之前被調用,因爲靜態塊將在類加載時調用(您的情況爲B類)。所以當你做

B.someStaticMethod() 

第一類B將被加載在靜態塊與它一起調用(JVM中的一次性進程),然後將調用靜態方法。

另請注意,導入語句以加載類不會加載類。當你在這個班上做一些操作時會發生這種情況。

+0

但是,因爲「B」類輸入了「A」,所以顯然會有依賴關係。爲什麼不是「A」初始化的第一個?另一個問題「A」被加載第一個正確的? 另外,如果A的初始化需要很長時間,我將如何知道它已被初始化? – nikel 2013-05-02 04:42:52

+0

請參閱我的更新回答 – 2013-05-02 04:45:37

+1

@nikel'import'僅用於編譯器的好處 - 它不會影響何時加載類。 – 2013-05-02 04:47:25

1

一個類可以有任意數量的靜態初始化塊,它們可以出現在類體的任何地方。運行時系統保證 靜態初始化塊的調用順序是它們在源代碼中出現的次數爲 。

Documentation

爲了它不可能是一個正確初始化之前靜態塊中被調用。

我覺得不會有什麼困惑,如果你初始化static比如像 -

靜一A =新的A();

+0

使用專有的建議,可能會導致問題... – nikel 2013-05-02 04:46:29

2

首先,在A被「正確初始化」之前調用靜態初始化器是可能的,但不是確定的。當B由類加載器加載時,將執行靜態初始化程序(請參閱#9:http://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.4.2)。我們沒有足夠的信息從你知道什麼時候會相對於被加載的A發生(B的靜態初始化器中的構造函數調用可能是第一次加載A,或者它可能很久以前發生過)。其次,一個被初始化的實例完全可能觸發A的初始化,使得所有東西都會自行完成。請記住,A的構造函數在類加​​載之前不會執行,其中包括爲A運行任何靜態初始值設定項。所以我不確定您擔心哪種類型的初始化可能不會發生。

第三,進口聲明與這些沒有任何關係。無論您完全限定com.foo.A使用導入語句,它的行爲都是相同的。

最後,如果你提供了一個真實的例子,它可能會有所幫助。如果A僅僅是一個日誌框架,那麼它就不是什麼專有的東西,你可能會得到一個更有用的答案,基於這個特定框架會發生什麼。

編輯:請參閱下面評論中提供的鏈接以獲取具體示例。

+0

+1 [This example](http://ideone.com/c3PNgy)可能會有用 - 將用於答案,但你覆蓋了我的一切會說。 – 2013-05-02 04:49:07

+0

這是不可能的。 – EJP 2013-05-02 04:54:22

+0

我們不知道他的意思是「正確初始化」。就我所知,還有一些其他進程必須在文件系統的某個位置創建日誌文件。類加載器的問題在這裏的各種答案中都有解釋,但是我很清楚他不僅僅關心類加載的含義,而且還有其他一些問題。也許我錯了他在問什麼。 – Shaun 2013-05-02 04:57:02

2

進口與它無關。運行時沒有導入。

引用在鏈接階段加載類,該鏈接階段位於初始化階段之前。在這種情況下,在B的靜態初始化程序執行之前,在B的鏈接解析步驟中加載A.

參考:JVM Specification: Loading, Linking, and Initializing

0

static A a; 靜態{a = new A(); } 這段代碼清楚的意思是代碼a = new A();將被調用並僅初始化一次,並在加載類直到主線程退出系統時保留在永久生成中。