Java 反射 Reflection

更多 Java 高級知識方面的文章,請參見文集《Java 高級知識》


Java 反射

在運行時:

  • 獲取類的成員變量和成員方法
  • 調(diào)用類的成員變量和成員方法
  • 通過構(gòu)造函數(shù)構(gòu)造一個類的對象

缺點:性能較差

getXX() VS getDeclaredXX():

  • getXX():包括繼承的
  • getDeclaredXX():不包括繼承的

Java 反射的使用

首先通過 Class.forName("") 顯示加載某個類延都,獲得 Class 對象乖篷,然后調(diào)用 Class 對象的如下方法:

  • Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
    • 通過參數(shù)列表,獲得某個構(gòu)造方法
    • 隨后可以調(diào)用 Constructor 類的 newInstance() 方法來創(chuàng)建對象
  • Method[] getDeclaredMethods()
    • 獲得所有的成員方法
    • Method 類包含如下方法:
      • String getName()
      • Class<?>[] getParameterTypes()
      • Class<?>[] getExceptionTypes()
      • Class<?> getReturnType()
      • Annotation[] getDeclaredAnnotations()
      • Class<?> getDeclaringClass()
  • Method getDeclaredMethod(String name, Class<?>... parameterTypes)
    • 通過方法名和參數(shù)列表,獲得某個成員方法
    • 如果只是通過方法名來獲得某個成員方法,則難以處理方法重載的情況
  • Field[] getDeclaredFields()
    • 獲得所有的成員變量
  • Field getDeclaredField(String name)
    • 通過變量名,獲得某個成員變量

使用 Java 反射 API 的時候可以繞過 Java 的訪問控制檢查矮冬,可以訪問私有成員變量和私有成員方法,只需在獲取 Constructor蚕断,MethodField 之后調(diào)用 .setAccessible(true)欢伏。

示例:

public class Student {
    private String name;
    private int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void print() {
        System.out.println(name + "-" + age);
    }
}

public static void main(String[] args) throws Exception {
    // 加載類,字節(jié)碼轉(zhuǎn)換為 Class 對象
    Class c = Class.forName("Student");

    // 獲取構(gòu)造方法并通過構(gòu)造方法構(gòu)造對象
    Constructor<Student> constructor = c.getDeclaredConstructor(String.class, int.class);
    Student student = constructor.newInstance("Tom", 18);

    // 獲取字段及對應的值
    Field[] fields = c.getDeclaredFields();
    for (Field field : fields) {
        // 設(shè)置可見性
        field.setAccessible(true);

        System.out.println(field.getName() + "=" + field.get(student));
    }

    // 獲取方法及執(zhí)行方法
    Method[] methods = c.getDeclaredMethods();
    for (Method method : methods) {
        method.invoke(student);
    }
}

反射中對泛型的處理

由于類型擦除機制亿乳,泛型中的類型參數(shù)在運行時是不存在的硝拧,JVM 只看到原始類型。
因此 Java5 在編譯后的 .class 中添加了 Signature 屬性葛假,用來包含不在 JVM 類型系統(tǒng)中的類型信息障陶,提供給反射 API 來使用。
例如:

public class Reflection_Test2 {

    public static void main(String[] args) throws Exception {
        // 加載類聊训,字節(jié)碼轉(zhuǎn)換為 Class 對象
        Class c = Class.forName("advanced.Ref");

        // 獲取字段及對應的值
        Field field = c.getDeclaredField("map");
        Type type = field.getType();
        // 輸出 java.util.HashMap
        System.out.println(type.getTypeName());

        Type genericType = field.getGenericType();
        // 輸出 java.util.HashMap<java.lang.String, java.lang.Integer>
        System.out.println(genericType.getTypeName());

        if (genericType instanceof ParameterizedType) {
            ParameterizedType pt = (ParameterizedType) genericType;

            Type[] actualTypeArguments = pt.getActualTypeArguments();
            for (Type actualTypeArgument : actualTypeArguments) {
                // 依次輸出 java.lang.String java.lang.Integer
                System.out.println(actualTypeArgument.getTypeName());
            }
        }
    }
}

class Ref {
    private HashMap<String, Integer> map;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末抱究,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子带斑,更是在濱河造成了極大的恐慌鼓寺,老刑警劉巖勋拟,帶你破解...
    沈念sama閱讀 221,820評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異妈候,居然都是意外死亡敢靡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,648評論 3 399
  • 文/潘曉璐 我一進店門苦银,熙熙樓的掌柜王于貴愁眉苦臉地迎上來啸胧,“玉大人,你說我怎么就攤上這事幔虏》哪睿” “怎么了?”我有些...
    開封第一講書人閱讀 168,324評論 0 360
  • 文/不壞的土叔 我叫張陵想括,是天一觀的道長陷谱。 經(jīng)常有香客問我,道長主胧,這世上最難降的妖魔是什么叭首? 我笑而不...
    開封第一講書人閱讀 59,714評論 1 297
  • 正文 為了忘掉前任习勤,我火速辦了婚禮踪栋,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘图毕。我一直安慰自己夷都,他們只是感情好,可當我...
    茶點故事閱讀 68,724評論 6 397
  • 文/花漫 我一把揭開白布予颤。 她就那樣靜靜地躺著囤官,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蛤虐。 梳的紋絲不亂的頭發(fā)上党饮,一...
    開封第一講書人閱讀 52,328評論 1 310
  • 那天,我揣著相機與錄音驳庭,去河邊找鬼刑顺。 笑死,一個胖子當著我的面吹牛饲常,可吹牛的內(nèi)容都是我干的蹲堂。 我是一名探鬼主播,決...
    沈念sama閱讀 40,897評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼贝淤,長吁一口氣:“原來是場噩夢啊……” “哼柒竞!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起播聪,我...
    開封第一講書人閱讀 39,804評論 0 276
  • 序言:老撾萬榮一對情侶失蹤朽基,失蹤者是張志新(化名)和其女友劉穎布隔,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體稼虎,經(jīng)...
    沈念sama閱讀 46,345評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡执泰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,431評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了渡蜻。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片术吝。...
    茶點故事閱讀 40,561評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖茸苇,靈堂內(nèi)的尸體忽然破棺而出排苍,到底是詐尸還是另有隱情,我是刑警寧澤学密,帶...
    沈念sama閱讀 36,238評論 5 350
  • 正文 年R本政府宣布淘衙,位于F島的核電站,受9級特大地震影響腻暮,放射性物質(zhì)發(fā)生泄漏彤守。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,928評論 3 334
  • 文/蒙蒙 一哭靖、第九天 我趴在偏房一處隱蔽的房頂上張望具垫。 院中可真熱鬧,春花似錦试幽、人聲如沸筝蚕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,417評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽起宽。三九已至,卻和暖如春济榨,著一層夾襖步出監(jiān)牢的瞬間坯沪,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,528評論 1 272
  • 我被黑心中介騙來泰國打工擒滑, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留腐晾,地道東北人。 一個月前我還...
    沈念sama閱讀 48,983評論 3 376
  • 正文 我出身青樓橘忱,卻偏偏與公主長得像赴魁,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子钝诚,可洞房花燭夜當晚...
    茶點故事閱讀 45,573評論 2 359

推薦閱讀更多精彩內(nèi)容