【Java 反射】Java反射的學習

1 參考資料

  1. https://how2j.cn/k/reflection/reflection-class/108.html 一個比較全面的Java學習教程(這裏用下人家的代碼)
  2. Java編程思想

2 反射的由來

假設自己從磁盤文件或者網絡獲取了一串字節,且被告知這串字節代表了一個類。然後,我們如何去使用這樣的一個類?
解決辦法----反射(Class類和java.lang.reflect類對反射概念進行了描述)

3 反射和RTTI的區別

很簡單,RTTI是在編譯時打開和檢查.class文件,反射是在運行時打開和檢查.class文件。

4 反射能幹嘛

4.1 獲取Class對象

這個就是三種方法獲取Class對象。
點它進去看詳細介紹
不點這也有圖( ̄▽ ̄)
在這裏插入圖片描述

4.2 創建對象

首先我們這裏得現有一個定義好的Hero類。

public class Hero {
    public String name;
    public float hp;
    public int damage;
    public int id;

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Hero(){

    }
    public Hero(String string) {
        name =string;
    }

    @Override
    public String toString() {
        return "Hero [name=" + name + "]";
    }
    public boolean isDead() {
        // TODO Auto-generated method stub
        return false;
    }
    public void attackHero(Hero h2) {
        System.out.println(this.name+ " 正在攻擊 " + h2.getName());
    }

}

然後我們來測試下,用反射方法創建新的Hero對象

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class ReflectDemo {
    public static void main(String[] args) throws IllegalAccessException,
            InstantiationException,
            NoSuchMethodException,
            InvocationTargetException {

        // Class 直接創建實例,但是該類必須要有一個無參的默認構造函數
        //只能反射無參的構造器,需要構造器可見;
        Class<Hero> heroClass = Hero.class;
        Hero hero = heroClass.newInstance();
        // 通過類的構造器創建實例,可以反射任何構造器,可以反射私有構造器
        Constructor<Hero> heroConstructor = heroClass.getConstructor(String.class);
        Hero hero1 = heroConstructor.newInstance("CC");

        System.out.println(hero.toString());
        System.out.println(hero1.toString());
    }
}

瞅瞅結果
在這裏插入圖片描述

4.3 修改屬性值

    Class<Hero> heroClass = Hero.class;
    Hero hero = heroClass.newInstance();

    hero.setName("CC");
    System.out.println("hero's Name is "+hero.getName());
    Field field = heroClass.getField("name");
    field.set(hero,"GG");
    System.out.println("hero's Name is "+hero.getName());

結果,
在這裏插入圖片描述
PS:getField 只能獲取public的,包括從父類繼承來的字段。
getDeclaredField 可以獲取本類所有的字段,包括private的,但是不能獲取繼承來的字段。
(注: 這裏只能獲取到private的字段,但並不能訪問該private字段的值,除非加上setAccessible(true))

4.4 調用方法

同理,這邊也很簡單了

 Class<Hero> heroClass = Hero.class;
        Hero h = heroClass.newInstance();

        // 獲取這個名字叫做setName,參數類型是String的方法
        Method m = heroClass.getMethod("setName", String.class);
        // 對h對象,調用這個方法
        m.invoke(h, "蓋倫");
        // 使用傳統的方式,調用getName方法
        System.out.println("hero's name is "+h.getName());

結果
在這裏插入圖片描述

5 ending 反射機制在我們平常的開發中自己使用得比較少,但是在支持其他特性中用的比較多。Spring就是一個例子,由於現在還沒學,就不展開講了。最後,文章若有問題歡迎指正~

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