JAVA之反射(一)

反射(一)

** 注:博主的這篇文章是在學習反射的時間寫的若有問題請及時聯繫博主進行修改 **java

何爲反射

 這裏也不說一些很官方的語言了,官方的說明看着頭痛,總之一句話,就是在JAVA的運行狀態的時候,能夠對任何一個類進行操做,這是一個能夠動態的獲取信息和動態的使用某個方法的能力咱們就叫他反射,在家看下名字就知道這項功能有多屌。api

反射經常使用到的方法

注:Class類表示正在運行的JAVA應用程序的接口;Class類沒有構造方法,是由java虛擬機自動建立的。

使用反射API

這裏先例舉幾個經常使用到的方法,這些是咱們此次教程所須要的方法,不是不少,其餘的我在之後的文章中寫出。

經過代碼的方式來了解這些方法如何使用

首先我建立個Student.java的類,裏面有三個屬性(name,age,xb),看代碼:
package net.cncandy.test;

public class Student {
    
    private String name;
    private int age;
    private boolean xb;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public boolean isXb() {
        return xb;
    }
    public void setXb(boolean xb) {
        this.xb = xb;
    }
    public Student(String name, int age, boolean xb) {
        super();
        this.name = name;
        this.age = age;
        this.xb = xb;
    }
    public Student() {
        
    }
}

接下來咱們要建立一個測試的類,我給他取名字叫作TestDeom,大家能夠根據本身來建立這個類哦。安全

咱們須要認識三中獲取類的方式:函數

  • 類名.class
  • Class.ForName 注:這個是一個方法,咱們須要往裏面傳遞參數,具體傳入什麼參數我接下來會說的呢,
  • 對象.getclass

當咱們建立好了測試的類後,咱們這裏講解的是反射,咱們固然要經過反射的方式來加載到JVM,這裏就須要我上面說的Class.forName的方式來加載,這個方法是返回的一個Class對象。學習

` Class studentClass = Class.forName("net.cncandy.test.Student"); `

> 參數這裏面填寫的是你的包名加上類的名字,返回的數據要**經過Class類型接受**。這個時候你使用System.out.println(studentClass);打印是否是發現控制檯有顯示出來類的信息。
好比我這裏顯示的是 **class net.cncandy.test.Student** 這裏的信息和你可能顯示不同,能夠咱們的包名是不同的,你要對應你本身的

分別經過該類的有參構造和無參構造來實例化對象

  類已經加載到了內存中了,咱們是否是應該建立個Student的對象呢,咱們都知道在平時普通的new一個對象的時候,其實默認是調用了該類的構造方法,那麼這裏也是如此咱們也須要拿到該類的構造方法,這小結咱們要須要如何獲取類的構造方法:測試

  • 新增須要知識:獲取構造方法
  • 使用的方法:getConstructor() 和 newInstance()

咱們看下如何經過無參的構造來實例化對象,這裏咱們只須要使用Class的對象點出newInstance()便可,這樣系統就會實例化一個對象。this

問:我調用了newInstance(),是如何實例化對象的呢?上面說要經過構造函數,我也沒有指定構造函數呀。
答:使用次方法系統會自動尋找類中的無參的構造方法,經過無參的構造來實例化對象。這裏你們能夠測試下,當你刪除類中的無參構造時,你再次運行代碼會出現錯誤。code

Class studentClass = Class.forName("net.cncandy.test.Student"); //加載類
            Student student = (Student)studentClass.newInstance(); //實際是使用的無參構造實例化對象
            student.setAge(16); //使用類中的方法
            System.out.println(student.getAge()); //輸出值,驗證是否成功複製

輸出的結果是16,證實咱們這種實例化對象的方法是對的對象

使用有參數的構造來實例化對象

  首先咱們要先拿到帶有參數的構造方法,在我上面寫的方法列表內有相關的方法,咱們這裏使用的是getConstructor()來獲取帶參的構造,先來了解下代碼:blog

Constructor constructor =studentClass.getConstructor(String.class,int.class,boolean.class);
            Student student = (Student) constructor.newInstance("Candy",20,true);
            System.out.println(student.getAge());

這裏你們看下的,在getConstructor()若是括號額你填的空則是使用的是空參數構造方法,填寫參數的意思是由於咱們每一個類中可能會存在大量重名的方法,好比咱們使用的方法重載,這裏能夠經過參數列表來區分使用的是哪個方法。當你傳入了參數的時候,在你使用newInstance時候你會發現代碼有提示說讓您傳入參數,這裏的參數就是你平時實例化對象時的實際參數。

如何經過反射來使用類中的方法

  咱們這裏能夠經過參考上面經過有參數的構造來實例化對象的代碼來處理使用類中的方法,其實這裏的思路是同樣的。遵循三個步驟(這裏對於我來講的是那個步驟)1.拿到類中的方法(Look,反射屌不屌)2.給方法傳遞參數,3.測試是否成功。這裏的獲取方法的方法是須要傳入兩個參數
參數一:你須要的方法的名稱
參數二:方法參數的類型,有多少寫多少,反正代碼裏面接受的是三個點可編長參數。
最後使用invoke方法來進行使用方法,兩個參數:
參數一:上面我們實例化的student。
參數二:你須要往這個方法裏面傳的值

Method method =  clzzClass.getDeclaredMethod("setAge", int.class);
            method.invoke(user, 20);
            System.out.println(user.getAge());

最後驗證輸出的是20

使用反射來操做屬性

  上面方法表格裏面給出了獲取屬性的方法getDeclaredField返回值是Field,咱們這裏能夠直接經過這個方法傳入須要得到的屬性名字,

Field field = studentClass.getDeclaredField("name");
            field.set(student, "Candy");
            System.out.println(student.getName());

固然咱們在設置屬性的值的時候咱們是經過set方法來設置的這個裏面須要傳入兩個參數,參數一:Student的對象,參數二:須要設置的值,運行程序能夠正確的輸出Candy。

注:這個獲取屬性的時候,若是有的屬性在類中是私有的屬性,那麼咱們在這裏修改值的時候會爆出java.lang.IllegalAccessException異常,因此這裏咱們還要加一句代碼setAccessible(true)這句話是避免安全檢查,這裏不作多的解釋,有興趣的能夠看下源碼。

相關文章
相關標籤/搜索