類中可以存在的成員: 類載入過程: 1、JVM會先去方法區中找有沒有類對應的.class存在,如果有,就直接使用;如果沒有,就把對應類的.class載入到方法區; 2、將.class載入到方法區的時候,分為兩部分,首先將非靜態內容載入到方法區的非靜態區域內; 3、再將靜態內容載入到方法區的靜態區域內 ...
類中可以存在的成員:
class A{ 靜態成員變數; 非靜態成員變數; 靜態函數; 非靜態函數; 構造函數 A(..){...} 靜態代碼塊 static{...} 構造代碼塊 {...} }
類載入過程:
1、JVM會先去方法區中找有沒有類對應的.class存在,如果有,就直接使用;如果沒有,就把對應類的.class載入到方法區;
2、將.class載入到方法區的時候,分為兩部分,首先將非靜態內容載入到方法區的非靜態區域內;
3、再將靜態內容載入到方法區的靜態區域內,載入完成後,對所有的靜態成員變數進行預設初始化;
4、所有靜態成員變數預設初始化後,進行顯示賦值;再執行靜態代碼塊;(執行靜態代碼塊和靜態成員變數顯示賦值無先後順序,與代碼順序有關,誰在前面先執行誰)
5、如果有繼承關係,載入子類的時候會先載入父類,在載入子類。
對象創建過程:
1、對象創建首先會在堆記憶體中開闢一塊空間,並分配一個地址;
2、將對象的所有非靜態成員載入到開闢的空間下,併為所有非靜態成員變數進行預設初始化;
3、調用構造函數進棧執行,在執行構造函數的時候,首先會執行構造函數中的隱式三步,再執行構造函數中的代碼;
隱式三步:
1、執行super語句,調用父類的構造函數;
2、對所有非靜態成員變數進行顯示賦值;
3、執行構造代碼塊;(非靜態成員變數顯示賦值和執行構造代碼塊無先後順序,由代碼順序決定,誰在前先執行誰);
4、執行完隱式三步後,再執行構造函數中的代碼,代碼執行完後彈棧;
5、將堆記憶體中開闢的空間地址賦值給一個引用對象,對象創建完成。
下麵用一段代碼來驗證一下類載入和對象創建過程(轉載自某位大牛):
1 //父類 2 public class Insect { 3 private int i = printInit("Insect:i"); 4 protected int j; 5 6 protected static int x1 = printInit("static Insect.x1 initialized"); 7 static{ 8 System.out.println("Insect靜態代碼塊"); 9 x1=80; 10 } 11 Insect() { 12 System.out.println("基類構造函數階段: i = " + i + ", j = " + j); 13 j = 39; 14 System.out.println(x1); 15 } 16 17 static int printInit(String s) { 18 System.out.println(s); 19 return 47; 20 } 21 22 } 23 //子類 24 public class Beetle extends Insect{ 25 { 26 k=90; 27 } 28 private int k = printInit("Beetle.k initialized"); 29 30 31 protected static int x2 = printInit("static Beetle.x2 initialized"); 32 33 34 public Beetle() { 35 System.out.println(k); 36 } 37 38 39 public static void main(String[] args) { 40 Beetle b = new Beetle(); 41 } 42 43 }
運行結果: