Java中類及方法的載入順序
1. 虛擬機器在首次載入Java類時,會對靜態程式碼塊、靜態成員變數、靜態方法進行一次初始化(靜態間按順序執行)。
2. 只有在呼叫new方法時才會建立類的例項。
3. 類例項建立過程:父子繼承關係,先父類再子類。父類的靜態->子類的靜態->父類的初始化塊->父類的構造方法->子類的初始化塊->子類的構造方法
4. 類例項銷燬時候:首先銷燬子類部分,再銷燬父類部分。
例:
輸出結果:package exercise; public class Main_exer { void myMethod(Object o){ System.out.println("object"); } void myMethod(String s){ System.out.println("string"); } public static void main(String[] args) { Main_exer ma = new Main_exer(); ma.myMethod(null); } }
string
例:
package classLoader_demo; public class Parent { //靜態成員變數 public static int t = parentStaticMethod2(); //程式碼塊 { System.out.println("父類非靜態初始化塊"); } static { System.out.println("父類靜態初始化塊"); } //構造方法 public Parent() { System.out.println("父類的構造方法"); } //父類靜態方法 public static int parentStaticMethod() { System.out.println("父類的靜態方法"); return 10; } public static int parentStaticMethod2() { System.out.println("父類的靜態方法2"); return 9; } @Override protected void finalize() throws Throwable { // TODO Auto-generated method stub super.finalize(); System.out.println("銷燬父類"); } }
當main中語句為package classLoader_demo; public class Child extends Parent { //程式碼塊 { System.out.println("子類非靜態初始化塊"); } static { System.out.println("子類靜態初始化塊"); } //構造方法 public Child() { System.out.println("子類的構造方法"); } //靜態方法 public static int childStaticMethod() { System.out.println("子類的靜態方法"); return 1000; } @Override protected void finalize() throws Throwable { // TODO Auto-generated method stub super.finalize(); System.out.println("銷燬子類"); } }
Parent.parentStaticMethod();
輸出結果:
父類的靜態方法2
父類靜態初始化塊
父類的靜態方法
當main中語句為
Child child = new Child();
try {
child.finalize();
} catch (Throwable e) {
e.printStackTrace();
}
輸出結果:
父類的靜態方法2
父類靜態初始化塊
子類靜態初始化塊
父類非靜態初始化塊
父類的構造方法
子類非靜態初始化塊
子類的構造方法
銷燬父類
銷燬子類
此處輸出結果中的先輸出“銷燬父類”,再輸出“銷燬子類”,與前面提到的先銷燬子類再銷燬父類並不矛盾。仍然為先呼叫子類的銷燬方法,再呼叫父類的銷燬方法,只是super關鍵字的原因。
備註:
1. Java中類方法和例項方法的區別
類體中的方法分為例項方法和類方法兩種,用static修飾的是類方法。
當類的位元組碼檔案被載入到記憶體時,類的例項方法不會被分配入口地址,當該類建立物件後,類中的例項方法才分配入口地址,從而例項方法可以被類建立的任何物件呼叫執行。需要注意的是,當我們建立第一個物件時,類中的例項方法就分配了入口地址,當再建立物件時,不再分配入口地址,也就是說,方法的入口地址被所有的物件共享,當所有的物件都不存在時,方法的入口地址才被取消。
對於類中的類方法,在該類被載入到記憶體時,就分配了相應的入口地址。從而類方法不僅可以被類建立的任何物件呼叫執行,也可以直接通過類名呼叫。類方法的入口地址直到程式退出才被取消。
類方法在類的位元組碼載入到記憶體時就分配了入口地址,因此,Java語言允許通過類名直接呼叫類方法,而例項方法不能通過類名呼叫。在講述類的時候我們強調過,在Java語言中,類中的類方法不可以操作例項變數,也不可以呼叫例項方法,這是因為在類建立物件之前,例項成員變數還沒有分配記憶體,而且例項方法也沒有入口地址。
2. Java程式執行時需載入的幾個類
例:
package classLoader_demo;
import java.net.URL;
public class Main_cld {
public static void main(String[] args) {
URL[] urls = sun.misc.Launcher.getBootstrapClassPath().getURLs();
for(int i=0; i < urls.length; i++){
System.out.println(urls[i].toExternalForm());
}
System.out.println("----- 分隔符------");
System.out.println(System.getProperty("sun.boot.class.path"));
}
}
輸出結果:
file:/C:/Program%20Files/Java/jre1.8.0_66/lib/resources.jar
file:/C:/Program%20Files/Java/jre1.8.0_66/lib/rt.jar
file:/C:/Program%20Files/Java/jre1.8.0_66/lib/sunrsasign.jar
file:/C:/Program%20Files/Java/jre1.8.0_66/lib/jsse.jar
file:/C:/Program%20Files/Java/jre1.8.0_66/lib/jce.jar
file:/C:/Program%20Files/Java/jre1.8.0_66/lib/charsets.jar
file:/C:/Program%20Files/Java/jre1.8.0_66/lib/jfr.jar
file:/C:/Program%20Files/Java/jre1.8.0_66/classes
----- 分隔符------
C:\Program Files\Java\jre1.8.0_66\lib\resources.jar;C:\Program Files\Java\jre1.8.0_66\lib\rt.jar;C:\Program Files\Java\jre1.8.0_66\lib\sunrsasign.jar;C:\Program Files\Java\jre1.8.0_66\lib\jsse.jar;C:\Program Files\Java\jre1.8.0_66\lib\jce.jar;C:\Program Files\Java\jre1.8.0_66\lib\charsets.jar;C:\Program
Files\Java\jre1.8.0_66\lib\jfr.jar;C:\Program Files\Java\jre1.8.0_66\classes