反射

反射

類加載器的概述

當程序要使用某個類時,如果該類還未被加載到內存中,
則系統會通過加載,連接,初始化三步來實現對這個類進行初始化。
加載
就是指將class文件讀入內存,併爲之創建一個Class對象。
任何類被使用時系統都會建立一個Class對象。
連接
驗證 : 是否有正確的內部結構,並和其他類協調一致
準備 : 負責爲類的靜態成員分配內存,並設置默認初始化值
解析: 把類中的符號引用轉換爲直接引用
初始化 就是我們以前講過的初始化步驟

類的加載時機

創建類的實例
訪問類的靜態變量,或者爲靜態變量賦值
調用類的靜態方法
使用反射方式來強制創建某個類或接口對應的java.lang.Class對象
初始化某個類的子類
直接使用java.exe命令來運行某個主類

類加載器的分類

Bootstrap ClassLoader 根類加載器
Extension ClassLoader 擴展類加載器
Sysetm ClassLoader 系統類加載器

類加載器的作用

Bootstrap ClassLoader 根類加載器
也被稱爲引導類加載器,負責Java核心類的加載
比如System,String等。在JDK中JRE的lib目錄下rt.jar文件中
Extension ClassLoader 擴展類加載器
負責JRE的擴展目錄中jar包的加載。
在JDK中JRE的lib目錄下ext目錄
Sysetm ClassLoader 系統類加載器
負責在JVM啓動時加載來自java命令的class文件,以及classpath環境變量所指定的jar包和類路徑

反射概述

JAVA反射機制是在運行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;
對於任意一個對象,都能夠調用它的任意一個方法和屬性;
這種動態獲取的信息以及動態調用對象的方法的功能稱爲java語言的反射機制。
要想解剖一個類,必須先要獲取到該類的字節碼文件對象。
而解剖使用的就是Class類中的方法,所以先要獲取到每一個字節碼文件對應的Class類型的對象

獲取class文件對象的三種方式

Object類的getClass()方法
靜態屬性class
Class類中靜態方法forName()
反射: 就是在運行狀態中的一種動態調用方法或者屬性的一種機制.

  • 就是獲取字節碼文件對象,然後剖析改類中存在哪些構造方法,哪些成員變量,哪些成員方法
    • 類的成員
    • 成員變量 Field
    • 構造方法 Constructor
    • 成員方法 Method
    • 如何獲取一個類對應的字節碼文件對象:
    • a: 第一種通過Object類中的getClass方法
    • b: 通過靜態屬性(class屬性)
    • c: 通過Class類中的一個靜態方法:
    • public static Class forName(String className):
    • className: 這個表示的是一個類對應的全類名(就是需要加上包名)

列:

public class Student {

public void test(){
    System.out.println("這是一個空參的方法");
}

public void test2(String name,int age) {
    System.out.println("這是一個有參的方法"+name+"==="+age);
}

public String show(String name, int age) {
    System.out.println("這是一個有參的方法" + name + "===" + age);

    return name+"哈哈";
}

private String show2(String name, int age) {
    System.out.println("這是一個有參的方法" + name + "===" + age);

    return name + "哈哈";
}

}
public class MyTest {
public static void main(String[] args) throws Exception{
Class aClass = Class.forName("org.westos.demo2.Student");
Object obj = aClass.newInstance();

    //獲取該類所有的成員方法對象,不包括私有的方法,包括父類繼承下來方法
    Method[] methods = aClass.getMethods();
    for (Method method : methods) {
        System.out.println(method.getName());
    }

    System.out.println("-----------------------");
    //獲取該類中所有的方法,包括私有的
    Method[] declaredMethods = aClass.getDeclaredMethods();
    for (Method m : declaredMethods) {
        System.out.println(m.getName());
    }

}

}
public class MyTest2 {
public static void main(String[] args) throws Exception{
Class aClass = Class.forName("org.westos.demo2.Student");
Object obj = aClass.newInstance();
//獲取單個的非私有方法的對象
Method test = aClass.getMethod("test");
System.out.println(test);

    ////以前要調用一個方法
    //Student student = new Student();
    //student.test();
    test.invoke(obj);

    System.out.println("--------------------");
    //獲取一個有參數的方法對象
    Method test2 = aClass.getMethod("test2", String.class, int.class);
    test2.invoke(obj,"abc",100);

    //獲取一個有參數,有返回值的方法對象,並調用該方法執行
    Method show = aClass.getMethod("show", String.class, int.class);
    Object result = show.invoke(obj, "張三", 19);
    String str= (String) result;
    System.out.println(str);

}

}
public class MyTest3 {
public static void main(String[] args) throws Exception {
Class aClass = Class.forName("org.westos.demo2.Student");
Object obj = aClass.newInstance();
//獲取一個私有的方法對象
Method show2 = aClass.getDeclaredMethod("show2", String.class, int.class);
show2.setAccessible(true);//取消語法檢測
show2.invoke(obj, "王五", 25);
}
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章