2015-10-20 58 views
6

嗯,我有這樣的代碼:當類加載?

public class Main { 
    public static void main(String[] args) { 
     Test t; //1 
     Integer i = new Integer(1); //2 
     t = new Test(); //3 
     System.out.println(Test4.a); //4 
    } 
} 

class Test { 
    private int a = 10; 
    private Test2 t2; //5 

    List<Test2> list = new ArrayList<Test2>() { 
     { 
      for (int i = 0; i < a; i++) { 
       add(new Test2()); //6 
      } 
     } 
    }; 
} 

class Test2 extends Test3{ 
} 

class Test3 { 
} 

class Test4 { 
    public static final int a = 4; 
} 

我不知道類裝入如何(全部或部分)和時間。所以:

  1. Test t; - 它不是一個有效使用時間,但參考t必須是一個明確的類型。是測試類加載(也許部分,然後有多少個階段 - 加載\鏈接\初始化 - 它通過)或沒有發生?
  2. Integer i = new Integer(1); - 在JVM啓動時或在此行上是整數加載的?
  3. t = new Test(); - 活動用法。它是從一開始或從某個點完全加載(請參閱1)
  4. System.out.println(Test4.a); - 是Test4加載與否?
  5. 是否已加載Test2Test3?如果是,那麼什麼時候?

回答

5

加載課程時覆蓋了JLS, Section 12.4.1

類或接口類型T將緊接在以下中的任何一個的第一次出現之前被初始化:

  • T是一個類並且創建T的實例。

  • T是一個類,由T聲明的靜態方法被調用。

  • 指定由T聲明的靜態字段。

  • 使用由T聲明的靜態字段,該字段不是常量變量(§4.12.4)。

  • T是一個頂級類(§7.6),並執行了一個在T(§8.1.3)中在詞彙上嵌套的斷言語句(§14.10)。

(剪斷)

類或接口將不會在任何其他情況下被初始化。

Chapter 5有關加載,鏈接和初始化類會談。

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

您的問題:

  1. 聲明一個變量不加載類。但加載發生在鏈接之前,並且鏈接發生在初始化之前。所以,當一個類被加載時,它也被鏈接和初始化。
  2. 在您的代碼運行之前,Integer類由JVM加載(以及許多其他語言基礎類)。
  3. 現在Test類被加載,因爲創建了一個新的實例。
  4. Test4未加載,因爲只使用了一個常量變量,這與上面的第4條規則衝突。
  5. Test3Test2Test被裝載之後裝載,因爲Test2對象被Test的實例初始化,這也造成Test3(超類)被加載創建。

這是running your code with the JVM option -verbose:class確認。

+0

注意初始化與加載(或鏈接)不同。 –

+0

如果** Test **類沒有在第(1)行加載,那麼什麼類型會有變量** t **? –

+0

在JVM中,變量't'還不存在;它尚未分配。 – rgettman