Java基礎(七)

框架是個好東西,可早晚有一天會過時,這世界上就沒有亙古不變的東西,來學下Java基礎吧

反射機制

Java語言的反射機制是指:在運行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法,對於任意一個對象,都能夠調用他的任意一個屬性和方法,這種動態獲取的信息以及動態調用對象的方法的功能成爲反射機制

如何獲取這些信息呢?依賴於Class對象,Class對象將一個類的方法,變量等信息告訴運行的程序

獲取Class對象的兩種方法:

已知類名爲TargetObject

- Class alunbarClass = TargetObject.class;
- Class alunbarClass1 = Class.forName("cn.luckycurve.TargetObject");

反射使用實例

供調用的TargetObject類

public class TargetObject {
    private String value;

    public TargetObject() {
        value = "LuckyCurve";
    }

    public void publicMethod(String name) {
        System.out.println("I love " + name);
    }

    private void privateMethod(String name) {
        System.out.println("I hate " + name);
    }

}

調用Target的Main類

public class Main {
    //    操作Traget類
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        Class<?> targetClass = Class.forName("cn.luckycurve.demo9.TargetObject");

//        從Java 9 開始不推薦使用以下寫法
//        TargetObject o = (TargetObject) targetClass.newInstance();
//        推薦寫法爲
        TargetObject target = (TargetObject) targetClass.getDeclaredConstructor().newInstance();

//        獲取類中的所有方法
        Method[] methods = targetClass.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println("method name :" + method.getName());
        }

//        獲取指定方法並調用,要指定方法名和參數信息
        Method publicMethod = targetClass.getDeclaredMethod("publicMethod", String.class);
//        由於是非靜態方法,要指定調用方法的對象
        publicMethod.invoke(target, "Java");

//        直接獲取和修改private類型的字段
        Field value = targetClass.getDeclaredField("value");
//        因爲value是private的,取消安全檢查,不然會拋出異常
        value.setAccessible(true);
        String string = (String) value.get(target);
        System.out.println("修改前 value:" + string);
        value.set(target,"LuckyCurve2");
        String string2 = (String) value.get(target);
        System.out.println("修改後 value:" + string2);

//        調用私有方法
        Method privateMethod = targetClass.getDeclaredMethod("privateMethod", String.class);
//        取消安全檢查
        privateMethod.setAccessible(true);
        privateMethod.invoke(target,"lazy");
    }
}

<<<method name :publicMethod
<<<method name :privateMethod
<<<I love Java
<<<修改前 value:LuckyCurve
<<<修改後 value:LuckyCurve2
<<<I hate lazy

總結:

​ 1.調用非靜態方法,要將對象傳進invoke方法中

​ 2.所有聲明爲private的字段和方法,在使用前都要調用feild.setAccessible(true)或者method.setAccessible(true)來解除安全檢查

靜態編譯和動態編譯

  • 靜態編譯:在編譯時確定類型,綁定對象
  • 動態編譯:在運行時確定類型,綁定對象

C++裏面有詳細的描述(C++的語言顆粒度細,程序很容易涉及到底層)

反射的優缺點

  • 優點:動態編譯,增加了靈活性
  • 缺點:運行效率低,需要JVM進行一系列解釋操作。安全問題,反射甚至可以操作私有字段和方法(也是優點,增加了靈活性 )

反射的應用場景

反射是框架的靈魂

雖然開發的時候很難用到反射機制,但也不能說明反射機制沒有什麼用,動態代理的設計模式,模塊化的開發,還有我們日常使用的Spring / Hibernate等框架,都大量用到了反射機制

  • JDBC連接數據庫時候使用了Class.forName
  • Spring框架的IOC以及AOP
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章