JAVA中的反射機制

今天帶大家看一下JAVA框架中必不可少的一個機制——反射

什么是反射?

JAVA反射機制是在運行狀態中,對于任意一個類,都能夠知道這個類的所有屬性和方法;對于任意一個對象,都能夠調用它的任意方法和屬性;這種動態獲取信息以及動態調用對象方法的功能稱為java語言的反射機制。
對反射的最初接觸是學習jdbc時,加載數據庫驅動時會這樣寫:Class.forName("com.mysql.jdbc.Driver"),當時似懂非懂的也不知道是什么意思,隨著自己的不斷學習,越來越感覺反射的神奇,讓我們一起來揭開它的神秘面紗吧。
學習一個知識,自然是最先從api開始,反射涉及的類,除了Class類之外,基本上都在java.lang.reflect包里面,常用的類有Constructor,Field,Method類等,AccessibleObject類是前面三個類的基類,主要包含設置安全性檢查等方法,下面,我們看一下reflect包的結構


image.png

反射能用來做什么呢?

我們知道反射機制允許程序在運行時取得任何一個已知名稱的class的內部信息,包括包括其modifiers(修飾符),fields(屬性),methods(方法)等,并可于運行時改變fields內容或調用methods。那么我們便可以更靈活的編寫代碼,代碼可以在運行時裝配,無需在組件之間進行源代碼鏈接,降低代碼的耦合度;還有動態代理的實現等等;但是需要注意的是反射使用不當會造成很高的資源消耗!

先來看一下反射的具體實現

下面是一個基本的類 Person

package com.qf.cdxt;
public class Person {
    //私有屬性
    private String name = "AME";
    //公有屬性
    public int age = 18;
    //構造方法
    public Person() {    
    }
    //私有方法
    private void eat(){
        System.out.println("private eat()...");
    }
    //公有方法
    public void play(){
        System.out.println("public play()...");
    }
}

①、得到 Class 的三種方式

//1、通過對象調用 getClass() 方法來獲取,通常應用在:比如你傳過來一個 Object
//  類型的對象,而我不知道你具體是什么類,用這種方法
  Person person1= new Person();
  Class c1 = person1.getClass();
        
//2、直接通過 類名.class 的方式得到,該方法最為安全可靠,程序性能更高
//  這說明任何一個類都有一個隱含的靜態成員變量 class
  Class c2 = Person.class;
        
//3、通過 Class 對象的 forName() 靜態方法來獲取,用的最多,
//   但可能拋出 ClassNotFoundException 異常
  Class c3 = Class.forName("com.ys.reflex.Person");

② 通過 Class 類獲取成員變量、成員方法、接口、超類、構造方法等
查閱 API 可以看到 Class 有很多方法:

getName():獲得類的完整名字。
  getFields():獲得類的public類型的屬性。
  getDeclaredFields():獲得類的所有屬性。包括private 聲明的和繼承類
  getMethods():獲得類的public類型的方法。
  getDeclaredMethods():獲得類的所有方法。包括private 聲明的和繼承類
  getMethod(String name, Class[] parameterTypes):獲得類的特定方法,name參數指定方法的名字,parameterTypes 參數指定方法的參數類型。
  getConstructors():獲得類的public類型的構造方法。
  getConstructor(Class[] parameterTypes):獲得類的特定構造方法,parameterTypes 參數指定構造方法的參數類型。
  newInstance():通過類的不帶參數的構造方法創建這個類的一個對象。

String className = c2.getName();
System.out.println(className);//輸出com.qf.cdxt.Person
        
//獲得類的public類型的屬性。
Field[] fields = c2.getFields();
for(Field field : fields){
   System.out.println(field.getName());//age
}
        
//獲得類的所有屬性。包括私有的
Field [] allFields = c2.getDeclaredFields();
for(Field field : allFields){
    System.out.println(field.getName());//name    age
}
        
//獲得類的public類型的方法。這里包括 Object 類的一些方法
Method [] methods = c2.getMethods();
for(Method method : methods){
    System.out.println(method.getName());//play waid equls toString hashCode等
}
        
//獲得類的所有方法。
Method [] allMethods = c2.getDeclaredMethods();
for(Method method : allMethods){
    System.out.println(method.getName());//play eat
}
        
//獲得指定的屬性
Field f1 = c2.getField("age");
System.out.println(f1);
//獲得指定的私有屬性
Field f2 = c2.getDeclaredField("name");
//啟用和禁用訪問安全檢查的開關,值為 true,則表示反射的對象在使用時應該取消 java 語言的訪問檢查;反之不取消
f2.setAccessible(true);
System.out.println(f2);
                
//創建這個類的一個對象
Object p2 =  c2.newInstance();
//將 p2 對象的  f2 屬性賦值為 Fy,f2 屬性即為 私有屬性 name
f2.set(p2,"Fy");
//使用反射機制可以打破封裝性,導致了java對象的屬性不安全。 
System.out.println(f2.get(p2)); //Fy
        
//獲取構造方法
Constructor [] constructors = c2.getConstructors();
for(Constructor constructor : constructors){
    System.out.println(constructor.toString());//public com.ys.reflex.Person()
}

上面呢就是一個反射機制的基本實現了。怎么樣是不是感覺很強大,這只是其中最簡單的一部分,我們后面的文章還會講到反射中更有意思的東西,大家有不同的意見或者是問題,歡迎大家在下方留言或者加入我的QQ群來找我(850353792)

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容