Java反射詳解

一、什么是反射?

“反射(Reflection)能夠讓運(yùn)行于JVM中的程序檢測和修改運(yùn)行時的行為。反射用于在運(yùn)行時檢測和修改某個對象的結(jié)構(gòu)及其行為。

二、Class反射機(jī)制

  • 指的是可以于運(yùn)行時加載,探知和使用編譯期間完全未知的類
  • 程序在運(yùn)行狀態(tài)中,,可以動態(tài)加載一個只有名稱的類, 對于任意一個已經(jīng)加載的類,都能夠知道這個類的所有屬性和方法; 對于任意一個對象,都能調(diào)用他的任意一個方法和屬性
  • 加載完類之后,產(chǎn)生一個Class類型的對象(一個類只有一個Class對象),這個對象包含了完整的類的結(jié)構(gòu)信息,而且這個Class對象就像一面鏡子,透過這個鏡子看到類的結(jié)構(gòu),所以被稱之為:反射
  • 每個類被加載進(jìn)入內(nèi)存之后,系統(tǒng)就會為該類生成一個對應(yīng)的java.lang.Class對象,通過該Class對象就可以訪問到JVM中的這個類

三、為什么需要反射?

  • 在運(yùn)行時檢測對象的類型
  • 動態(tài)構(gòu)造某個類的對象
  • 檢測類的屬性和方法
  • 任意調(diào)用對象的方法
  • 修改構(gòu)造函數(shù)、方法、屬性的可見性

四、反射的基本使用

1 Java反射主要API

在java.lang.reflect包中有三個重要的類:

  • Field:描述類的域
  • Method:描述類的方法
  • Constructor:描述類的構(gòu)造器

對于public域(包括超類成員):

  • getFields
  • getMethods
  • getConstructors

對于其它域(包括私有和受保護(hù)的成員,不包括超類成員):

  • gettDeclaredFields
  • gettDeclaredMethods
  • gettDeclaredConstructors

2 獲取class對象的三種方式

  • 對象的getClass()方法;
  • 類的.class(最安全/性能最好)屬性;
  • 運(yùn)用Class.forName(String className)動態(tài)加載類,className需要是類的全限定名(最常用).

例如對于如下的Person類:

package com.yano.reflect;

public class Person {

    public String name = "default name";
    public int[] array = new int[10];

    public Person() {
        System.out.println(name);
        for (int i = 0; i < array.length; i++) {
            array[i] = i;
        }
    }

    private Person(String name) {
        this.name = name;
        System.out.println(name);
    }

    public void fun() {
        System.out.println("fun");
    }

    public void fun(String name) {
        System.out.println(name);
    }

}

獲取Person對象的三種方式為:

// 加載類的3種方法
Class clazz = Class.forName("com.yano.reflect.Person");
Class clazz1 = new Person().getClass();
Class class2 = Person.class;

3 構(gòu)造函數(shù)的獲取

獲取類的無參構(gòu)造函數(shù),并實(shí)例化類:

Class clazz = Class.forName("com.yano.reflect.Person");
Constructor c = clazz.getConstructor(null);
Person p = (Person) c.newInstance(null);

獲取類的含參私有構(gòu)造函數(shù),并實(shí)例化類:

Class clazz = Class.forName("com.yano.reflect.Person");
Constructor c = clazz.getDeclaredConstructor(new Class[] { String.class });
// 由于構(gòu)造函數(shù)是 private 的,所以需要屏蔽Java語言的訪問檢查
c.setAccessible(true);
Person p = (Person) c.newInstance(new Object[] { "I'm a reflect name!" });

4 類方法的調(diào)用

獲取并調(diào)用類的無參方法:

Class clazz = Class.forName("com.yano.reflect.Person");
Constructor c = clazz.getConstructor(null);
Person p = (Person) c.newInstance(null);
Method method = clazz.getMethod("fun", null);
method.invoke(p, null);

獲取并調(diào)用類的含參方法:

Class clazz = Class.forName("com.yano.reflect.Person");
Constructor c = clazz.getConstructor(null);
Person p = (Person) c.newInstance(null);
Method method = clazz.getMethod("fun", new Class[] {String.class});
method.invoke(p, new Object[] { "I'm a reflect method!" });

5 類字段的訪問

獲取類字段:

Class clazz = Class.forName("com.yano.reflect.Person");
Constructor c = clazz.getDeclaredConstructor(new Class[] { String.class });
// 由于構(gòu)造函數(shù)是 private 的,所以需要獲取控制權(quán)限
c.setAccessible(true);
Person p = (Person) c.newInstance(new Object[] { "I'm a reflect name!" });
Field f = clazz.getField("name");
Object value = f.get(p);
Class type = f.getType();
System.out.println(type);
if (type.equals(String.class)) {
    System.out.println((String) value);
}

參考文章

Java 反射詳解
Java反射教程
粗淺看 java反射機(jī)制
Java 反射

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)載注明出處:http://www.itdecent.cn/p/2f488de72886 簡介 Java在編譯時候...
    王三的貓阿德閱讀 1,358評論 0 2
  • 今天是二零一六年十一月十七日。這是第十篇簡書。 我是喜歡喜劇結(jié)尾的,有很長一段時間,在網(wǎng)上找些小說或劇來看來聽的時...
    塵___世_美閱讀 199評論 0 1
  • 玄奘譯本 觀自在菩薩,行深般若波羅蜜多時,照見五蘊(yùn)皆空,度一切苦厄。 舍利子,色不異空,空不異色,色即是空,空即是...
    白語金言閱讀 194評論 1 1

友情鏈接更多精彩內(nèi)容