反射

反射是JAVA開發的高級特性,官方概念如下:

JAVA反射機制是在運行狀態中,對於任意一個實體類,都能夠知道這個類的所有屬性和方法;對於任意一個對象,都能夠調用它的任意方法和屬性;這種動態獲取信息以及動態調用對象方法的功能稱爲java語言的反射機制。

其實就是,反射可以知道任意類或對象的屬性和方法,

比如,我建立了一個student類如下,內含公有,私有的屬性和方法:

package com.imooc.demo.entity;

public class Student {
    public Integer id;
    public Integer gender;
    private String phoneNumber;
    private String address;
    private String name;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getGender() {
        return gender;
    }

    public void setGender(Integer gender) {
        this.gender = gender;
    }

    public String getPhoneNumber() {
        return phoneNumber;
    }

    public void setPhoneNumber(String phoneNumber) {
        this.phoneNumber = phoneNumber;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Deprecated
    private void print(String name) {
        System.out.println(name);
    }
}

然後再建立一個類,命名爲reflect類,以下代碼有4種方法獲取類的屬性和方法。

1.class.forname。可以直接在後面的括號里加上全限定名,用一個變量的泛型名稱接着,用這個studentClass來調用屬性或方法。

2.已經知道是哪個類,並且這個類就在本地代碼中,等號右邊直接用Student.class

3.new一個object類的對象,用這個對象來getclass。

4.用當前線程的類加載器,加載已知全限定名的類即可。

public class Reflact {

    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
//        Class<?> studentClass = Class.forName("com.imooc.demo.entity.Student");
//        Class<?> studentClass = Student.class;
//        Object student = new Student();new
//        Class<?> studentClass = student.getClass();
        Class<?> studentClass = Thread.currentThread().getContextClassLoader().loadClass("com.imooc.demo.entity.Student");

獲得了studentclass,就可以調用它的方法了。

//獲取聲明過的所有方法,包括公有和私有的方法
        Field[] declaredFields = studentClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField.getName());
        }
//獲取該類和父類的公有方法。該方法和上述方法各有利弊
        Field[] declaredFields = studentClass.getFields();

//可以調用私有方法
        Method method = studentClass.getDeclaredMethod("print", String.class);
        System.out.println(method.getReturnType());
//可以調用註解的方法。萬物皆對象,這裏的註解也可以認爲是對象。
        Annotation[] annotations = method.getAnnotations();
//        for (Annotation annotation : annotations) {
//            System.out.println(annotation.toString());
//
//        }

創建未知類的對象,並調用私有方法。

//用已經承接好的studentclass,創建一個新的對象,(用newinstance),
因爲此場景常用於框架,中間件等。不知道student類是否存在,所以此時不用new的方式,而是newinstance來創建對象。
並且invoke裏要填寫該私有方法的實參。如果現實該方法不可執行,我們可以用setAccessible來強制執行。

        method.setAccessible(true);
        method.invoke(studentClass.newInstance(),"xgx");

這些要用在什麼場景呢,比如單元測試,我們用mock儘量覆蓋所有的方法,但有些靜態方法,用普通的單元測試覆蓋不了,此時可以用反射來獲取方法。

發佈了45 篇原創文章 · 獲贊 10 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章