day43-反射02( 三 )


靜態加載的類,即使沒有用到也會加載,并且進行語法的校驗
  • 動態加載:運行時加載相關的類,如果運行時不用該類,即使不存在該類,也不會報錯,降低了依賴性
  • 類加載的時機:
    1. 當創建對象時(new)//靜態加載
    2. 當子類被加載時 //靜態加載
    3. 調用類中的靜態成員時 //靜態加載
    4. 通過反射 //動態加載
  • 例子:靜態加載和動態加載
    import java.lang.reflect.*;import java.util.*;public class classLoad_ {public static void main(String[] args) throws Exception {Scanner scanner = new Scanner(System.in);System.out.println("請輸入key");String key = scanner.next();switch (key) {case "1":Dog dog = new Dog();//靜態加載,依賴性很強dog.cry();break;case "2"://反射 -->動態加載Class cls = Class.forName("Person"); //加載Person[動態加載]Object o = cls.newInstance();Method m = cls.getMethod("hi");m.invoke(o);System.out.println("ok");break;default:System.out.println("do nothing...");}}}//因為new Dog()是靜態加載,因此必須編寫Dog//Person類是動態加載,所以即使沒有編寫Person類也不會報錯,只有當動態加載該類時,(有問題)才會報錯class Dog{public void cry(){System.out.println("小狗在哭泣..");}}在沒有編寫Dog類時,即使在switch選擇中,不一定會運行到new dog對象的case1,但是程序仍然報錯了 , 因為靜態加載的類,即使沒有用到,也會加載,并且進行語法的校驗
    day43-反射02

    文章插圖
    在編寫了Dog類對象后,可以看到編譯通過:
    day43-反射02

    文章插圖
    運行程序:可以看到,即使沒有編寫Person類 , 但是運行時沒有用到,就不會報錯
    day43-反射02

    文章插圖
    使用到Person類,報錯:(運行時加載)
    day43-反射02

    文章插圖
    6.類的加載過程
    • 類加載過程圖

    day43-反射02

    文章插圖
    • 類加載各階段完成的任務
      • 加載階段:將類的class文件讀入內存 , 并為之創建一個java.lang.Class對象 。此過程由類加載器完成 。
      • 連接階段:將類的二進制數據合并到jre中
      • 初始化階段:JVM負責對類進行初始化,這里主要是指靜態成員
    6.1.1加載階段
    day43-反射02

    文章插圖
    JVM 在該階段的主要目的是,將字節碼從不同的數據源(可能是class文件,也可能是jar包 , 甚至網絡)轉化為二進制字節流加載到內存中,并聲稱一個代表該類的java.lang.Class對象
    day43-反射02

    文章插圖
    6.1.2連接階段-驗證
    day43-反射02

    文章插圖
    1. 目的是為了確保Class文件的字節流中包含的信息符合當前虛擬機的要求,并且不會危害虛擬機自身的安全
    2. 包括:文件格式驗證(是否以 魔數 oxcafebabe開頭)、元數據驗證、字節碼驗證和符號引用驗證

    day43-反射02

    文章插圖
    1. 可以考慮使用 -Xverify:none 參數關閉大部分的類驗證措施,縮短虛擬機類加載的時間
    6.1.3連接階段-準備
    day43-反射02

    文章插圖
    JVM會在該階段對靜態變量,分配內存并默認初始化(對應的數據類型的默認初始值,如0,0L,null,false等) 。這些變量所使用的內存都將在方法區中進行分配
    例如:
    package li.reflection.classload_;//我們說明一個類加載的鏈接階段-準備public class ClassLoad02 {public static void main(String[] args) {}}class A {//屬性-成員變量-字段//一個類加載的鏈接階段中的準備階段 屬性是如何處理的//1. n1 是實例變量,不是靜態變量,因此在準備階段,是不會分配內存的//2. n2 是靜態變量,分配內存 n2 , 且默認初始化為 0,而不是20//3. n3 是static final , 是常量,它和靜態變量不一樣,因為一旦賦值就不變,n3 = 30public int n1 = 10;public static int n2 = 20;public static final int n3 = 30;}6.1.4連接階段-解析
    day43-反射02

    推薦閱讀