最簡單易懂的Java反射機制

Java反射機制是肥腸重要的概念,它的原理以及如何使用,一起來探討吧!

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

上面說的是反射的官方概念,其意思也就是,正常實例化對象的方式是:1、首先引入需要的包 2、new實例化 3、取得實例化對象 。而反射機制是“反”過來,通過實例化對象,可以獲得此對象的屬性,方法,所屬類包的名稱。反射是被視爲動態語言的關鍵,反射機制允許程序在執行期藉助於 Reflection API 取得任何類的內部信息,並能直接操作任意對象的內部屬性及方法。可以降低程序的耦合度,很多框架都運用了反射。

上面提到了反射是動態語言的關鍵,那麼,上面是“動態語言”呢?

動態語言是指程序運行時,允許改變程序結構或變量類型,這種語言稱爲動態語言。C++,Java,C#都不是動態語言。儘管在這樣的定義與分類下Java不是動態語言,它卻有着一個非常突出的動態相關機制:Reflection。這個字的意思是“反射、映象、倒影”,用在Java身上指的是我們可以於運行時加載、探知、使用編譯期間完全未知的classes。

Java的反射機制有什麼功能?

  • 在運行時判斷任意一個對象所屬的類;
  • 在運行時構造任意一個類的對象;
  • 在運行時判斷任意一個類所具有的成員變量和方法;
  • 在運行時調用任意一個對象的方法;
  • 生成動態代理

反射機制的相關類

類名 用途
Class 代表類的實體,在運行的Java應用程序中表示類和接口
Field 代表類的成員變量
Method 代表類的方法
Constructor 代表類的構造方法

Class類

1、創建Person類的對象

//Person.class 代表Person類
Class c = Person.class;
//創建Person類的實例p,相當於不使用反射創建的實例:Person p = new Person();
Person p = (Person)c.newInstance();

2、通過運行時類的對象,調用其getClass()方法,返回其運行時類。

Person per = new Person();
Class clazz = per.getClass();
System.out.println(clazz);

3、獲取Class類的四種方式:

//1、調用運行時類本身的 .class 屬性
Class c1 = Person.class;
//打印TestReflection.Person
System.out.println(clazz.getName());

Class c2= String.class;
//打印java.lang.String
System.out.println(c2.getName());


//2、 通過運行時類的對象獲取
Person person = new Person();
Class c3 = person.getClass();
//打印TestReflection.Person
System.out.println(c3.getName());


//3、通過 class 的靜態方法獲取
String className = "TestReflection.Person";
Class c4 = Class.forName(className);
//打印TestReflection.Person
System.out.println(c4.getName());


//4、類的加載器
String className = "TestReflection.Person";
ClassLoader classLoader = this.getClass().getClassLoader();
Class c5 = classLoader.loadClass(className);
//打印TestReflection.Person
System.out.println(c5.getName());

Field類

1、獲取Person類的訪問控制符爲public的指定成員變量

//Person.class 代表Person類
Class c = Person.class;

//創建Person類的實例p,相當於不使用反射創建的實例:Person p = new Person();
Person p = (Person)c.newInstance();

//獲取類Person的public屬性 name
Field f1 = c.getField("name");

//設定 Person類的對象 p 的 name 屬性爲 "Nikita",當Person的name屬性的訪問控制符爲 public 時纔可設定屬性值。
f1.set(p,"Nikita");

//打印Nikita
System.out.println(p.name);

2、獲取Person類的訪問控制符爲private的指定成員變量

//獲取聲明的Person類的private屬性 age
Field f2 = c.getDeclaredField("age");
//使用反射機制訪問私有變量時必須調用 setAccessible方法設置屬性爲true,否則會報 IllegalAccessException異常
f2.setAccessible(true);
//設置Person類的對象p的age屬性值爲 34
f2.set(p,34);
//打印 34
System.out.println(p.getAge());

3、獲取Person類的所有 public屬性

Class cla = Person.class;
//getFields():獲取運行時類中及其父類中所有public屬性
Field[] fields = cla.getFields();
for(int i =0;i<fields.length;i++) {
	//打印:public java.lang.String TestReflection.Person.name
    System.out.println(fields[i]);
}

4、獲取 Person類的所有屬性(包括private)

Class cla = Person.class;
//getDeclaredFields():獲取運行時類本身的所有屬性(包括private)
Field[] fields1 = cla.getDeclaredFields();
for(Field f:fields1){
    System.out.println(f.getName());
}

Method類

1、獲取Person類的 getAge()方法

Class c = Person.class;
Person p = (Person)c.newInstance();
//獲取Person類的 getAge方法
Method m1 = c.getMethod("getAge");
//Person類的對象p調用獲取的 getAge 方法,如果此方法有參數,invoke第二個參數是 調用getAge方法需要的參數。
m1.invoke(p);

2、獲取Person類的 display()方法

Class c = Person.class;
Person p = (Person)c.newInstance();
//獲取 Person 類的 display方法,第二個參數爲 display方法的參數類型
Method m2 = c.getMethod("display", String.class);
//調用display方法,參數爲"CHN is very good!"
m2.invoke(p,"CHN is very good!");

3、getMethods():獲取運行時類及其父類中所有聲明爲 public 的方法

Class ccc = Person.class;
Method[] method1 = ccc.getMethods();
for(Method m :method1) {
    System.out.println(m);
}

4、getDeclareMethods():獲取運行時類的所有方法(包括 private)

Class ccc = Person.class;
Method[] method2 = ccc.getDeclareMethods();
for(Method m :method2) {
    System.out.println(m);
}

Constructor類

獲取類中所有構造函數

String className = "TestReflection.Person";
Class c = Class.forName(className);
Constructor[] cons = c.getDeclaredConstructors();
    for(Constructor con : cons){
        System.out.println(con);
    }
}

獲取類的完整結構

包括:註解、權限修飾符、返回值類型、方法名、形參列表、異常類型

public  void test3() throws Exception{
       //獲取類中方法的完整結構
       Class c = Person.class;
       Method[] method = c.getDeclaredMethods();
       for(Method m : method) {
           //1、註解
           Annotation[] ann = m.getAnnotations();
           for(Annotation a:ann){
               System.out.print(a);
           }

           //2、權限修飾符
           String str = Modifier.toString(m.getModifiers());
           System.out.print(str+" ");

           //3、返回值類型
           Class returnType = m.getReturnType();
           System.out.println(returnType.getName()+" ");

           //4、方法名
           System.out.println(m.getName());

           //5、形參列表
           System.out.print("(");
           Class[] params = m.getParameterTypes();
           for(int i = 0;i<params.length;i++){
               System.out.print(params[i].getName()+" args-"+i+" ");
           }
           System.out.println(")");

           //6、異常類型
           Class [] exps = m.getExceptionTypes();
           if(exps.length != 0){
               System.out.print("throws ");
           }
           for(int i = 0;i < exps.length;i++) {
               System.out.print(exps[i].getName() + "");
           }
       }
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章