Java反射機制


說到反射,相信有過編程經驗的人都不會陌生。反射機制讓Java變得更加的靈活。反射機制在Java的眾多特性中是非常重要的一個。下面就讓我們一點一點了解它是怎么一回事。


什么是反射

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


反射有什么用

1,在運行時判斷任意一個對象所屬的類;

2,在運行時構造任意一個類的對象;

3,在運行時判斷任意一個類所具有的成員變量和方法;

4,在運行時調用任意一個對象的方法;

5,生成動態代理。


反射的API

學習一門語言,一種比較好的方式就是看它的API文檔,因為它的API是最權威的,最准確的。下面我們一起看看JDK的API對於反射是如何描述的吧!


與反射有關的所有接口以及類都在java.lang.reflect包里。


接口

接口摘要

AnnotatedElement

表示目前正在此 VM 中運行的程序的一個已注釋元素。

GenericArrayType

GenericArrayType 表示一種數組類型,其組件類型為參數化類型或類型變量。

GenericDeclaration

聲明類型變量的所有實體的公共接口。

InvocationHandler

InvocationHandler 是代理實例的調用處理程序 實現的接口。

Member

成員是一種接口,反映有關單個成員(字段或方法)或構造方法的標識信息。

ParameterizedType

ParameterizedType 表示參數化類型,如 Collection<String>。

Type

Type 是 Java 編程語言中所有類型的公共高級接口。

TypeVariable<D extends GenericDeclaration>

TypeVariable 是各種類型變量的公共高級接口。

WildcardType

WildcardType 表示一個通配符類型表達式,如 ?、? extends Number 或 ? super Integer。


類摘要

AccessibleObject

AccessibleObject 類是 Field、Method 和 Constructor 對象的基類。

Array

Array 類提供了動態創建和訪問 Java 數組的方法。

Constructor<T>

Constructor 提供關於類的單個構造方法的信息以及對它的訪問權限。

Field

Field 提供有關類或接口的單個字段的信息,以及對它的動態訪問權限。

Method

Method 提供關於類或接口上單獨某個方法(以及如何訪問該方法)的信息。

Modifier

Modifier 類提供了 static 方法和常量,對類和成員訪問修飾符進行解碼。

Proxy

Proxy 提供用於創建動態代理類和實例的靜態方法,它還是由這些方法創建的所有動態代理類的超類。

ReflectPermission

反射操作的 Permission 類。



下面給大家寫了一個小實例:

[java]  view plain copy 在CODE上查看代碼片 派生到我的代碼片
  1. package reflection;  
  2.   
  3. public class UserInfo {  
  4.       
  5.     private Integer id;  
  6.     private String userName;  
  7.     private String password;  
  8.     public Integer getId() {  
  9.         return id;  
  10.     }  
  11.     public void setId(Integer id) {  
  12.         this.id = id;  
  13.     }  
  14.     public String getUserName() {  
  15.         return userName;  
  16.     }  
  17.     public void setUserName(String userName) {  
  18.         this.userName = userName;  
  19.     }  
  20.     public String getPassword() {  
  21.         return password;  
  22.     }  
  23.     public void setPassword(String password) {  
  24.         this.password = password;  
  25.     }  
  26.       
  27.     @Override  
  28.     public String toString(){  
  29.         return this.getClass().getName();  
  30.     }  
  31.       
  32. }  


[java]  view plain copy 在CODE上查看代碼片 派生到我的代碼片
  1. package reflection;  
  2.   
  3. public class GetClass {  
  4.   
  5.     public boolean ClassCheck(){  
  6.         try {  
  7.               
  8.             System.out.println("第一種,通過類本身獲得對象");  
  9.             Class UserClass = this.getClass();  
  10.             System.out.println("第一種方式成功!類名:"+UserClass.toString()+"\n");  
  11.               
  12.             System.out.println("第二種,通過子類實例獲取父類");  
  13.             UserInfo ui = new UserInfo();  
  14.             UserClass = ui.getClass();  
  15.             Class SubUserClass = UserClass.getSuperclass();  
  16.             System.out.println("第二種方式成功!類名:"+SubUserClass.toString()+"\n");  
  17.               
  18.             System.out.println("第三種,通過類名加.class獲得對象");  
  19.             Class ForClass = reflection.UserInfo.class;  
  20.             System.out.println("第三種方式成功!類名:"+ForClass.toString()+"\n");  
  21.               
  22.             System.out.println("第四種,通過類名的字符串獲得對象");  
  23.             Class ForName = Class.forName("reflection.UserInfo");  
  24.             System.out.println("第四種方式成功!類名:"+ForName.toString()+"\n");  
  25.               
  26.         } catch (Exception e) {  
  27.             e.printStackTrace();  
  28.             return false;  
  29.         }  
  30.         return true;  
  31.     }  
  32.       
  33.     @Override  
  34.     public String toString(){  
  35.         return this.getClass().getName();  
  36.     }  
  37.       
  38.     public static void main(String[] args) {  
  39.         GetClass gc = new GetClass();  
  40.         gc.ClassCheck();  
  41.         if (gc.ClassCheck()) {  
  42.             System.out.println("所有反射全部成功!");  
  43.         }  
  44.         else {  
  45.             System.out.println("反射有問題,請檢查!");  
  46.         }  
  47.     }  
  48.   
  49. }  

上面四種方法里面,我用的最多的是第四種,這種一般都是配合配置文件一起用的。反射與配置文件的結合讓我們的代碼變得非常的靈活,易擴展、以維護。可謂是好處多多呀,所以才有那句”反射反射,程序員的快樂!“一起盡情的快樂吧!



實例一:獲得完整的類名

[java]  view plain copy 在CODE上查看代碼片 派生到我的代碼片
  1. package reflection.getclassname;  
  2.   
  3. //獲得完整的類名  
  4. public class GetClassName {  
  5.   
  6.     public String getNameByClass() {  
  7.           
  8.         String name = "";  
  9.         System.out.println("通過類本身獲得對象");  
  10.         Class UserClass = this.getClass();  
  11.         System.out.println("獲得對象成功!\n");  
  12.           
  13.         System.out.println("通過類對象獲得類名");  
  14.         name = UserClass.getName();  
  15.         System.out.println("獲得類名成功!");  
  16.         return name;  
  17.     }  
  18.     public static void main(String[] args) {  
  19.           
  20.         GetClassName gcn = new GetClassName();  
  21.         System.out.println("類名為:"+gcn.getNameByClass());  
  22.     }  
  23.   
  24. }  

運行結果:

通過類本身獲得對象
獲得對象成功!

通過類對象獲得類名
獲得類名成功!
類名為:reflection.getclassname.GetClass Name       



實例二:獲得類的屬性

[java]  view plain copy 在CODE上查看代碼片 派生到我的代碼片
  1. package reflection.getfields;  
  2.   
  3. import java.lang.reflect.Field;  
  4.   
  5. //獲得類的屬性  
  6. public class GetFields {  
  7.   
  8.     public static void getFieldNames(String className) {  
  9.           
  10.         try {  
  11.             //獲得類名  
  12.             Class c = Class.forName(className);  
  13.             //獲得所有屬性  
  14.             Field[] fds = c.getFields();  
  15.               
  16.             for (int i=0; i<fds.length; i++)  
  17.             {  
  18.                 String fn = fds[i].getName();  
  19.                 Class tc = fds[i].getType();  
  20.                 String ft = tc.getName();  
  21.                 System.out.println("該屬性的名字為:"+fn+",該屬性的類型為:"+ft);  
  22.             }  
  23.         }catch (Exception e) {  
  24.             e.printStackTrace();  
  25.         }  
  26.     }  
  27.       
  28.     public static void main(String[] args) {  
  29.         GetFields.getFieldNames("reflection.getfields.FieldInfo");  
  30.     }  
  31.   
  32. }  

運行結果:

該屬性的名字為:id,該屬性的類型為:java.lang.String

該屬性的名字為:username,該屬性的類型為:java.lang.String    



實例三:獲得類實現的接口

[java]  view plain copy 在CODE上查看代碼片 派生到我的代碼片
  1. package reflection.getinterfaces;  
  2.   
  3. //獲得類實現的接口  
  4. public class GetInterfaces {  
  5.   
  6.     public static void getInterfaces(String className) {  
  7.         try {  
  8.             //取得類  
  9.             Class cl = Class.forName(className);  
  10.             Class[] ifs = cl.getInterfaces();  
  11.             for (int i = 0; i<ifs.length;i++)  
  12.             {  
  13.                 String IName = ifs[i].getName();  
  14.                 System.out.println("該類實現的接口名字為:"+IName);  
  15.             }  
  16.         }catch (Exception e) {  
  17.             e.printStackTrace();  
  18.         }  
  19.     }  
  20.       
  21.     public static void main(String[] args) {  
  22.         GetInterfaces.getInterfaces("reflection.getinterfaces.Student");  
  23.     }  
  24.   
  25. }  

運行結果:

該類實現的接口名字為:reflection.getinterfaces.Person    



實例四:獲得類及其屬性的修飾符

[java]  view plain copy 在CODE上查看代碼片 派生到我的代碼片
  1. package reflection.getmodifiers;  
  2.   
  3. import java.lang.reflect.Field;  
  4. import java.lang.reflect.Modifier;  
  5.   
  6. import reflection.UserInfo;  
  7.   
  8. //獲得類及其屬性的修飾符  
  9. public class GetModifiers {  
  10.   
  11.     private String username = "liu shui jing";  
  12.     float f = Float.parseFloat("1.000");  
  13.     public static final int i = 37;  
  14.       
  15.     //獲得類的修飾符  
  16.     public static String useModifiers(UserInfo ui) {  
  17.           
  18.         Class uiClass = ui.getClass();  
  19.         int m = uiClass.getModifiers();  
  20.         return Modifier.toString(m);  
  21.           
  22.     }  
  23.       
  24.     //獲得本類屬性的修飾符  
  25.     public void checkThisClassModifiers() {  
  26.           
  27.         Class tc = this.getClass();       
  28.         Field fl[] = tc.getDeclaredFields();  
  29.       
  30.         for(int i=0;i<fl.length;i++)  
  31.         {  
  32.             System.out.println("第"+(i+1)+"個屬性的修飾符為:"+Modifier.toString(fl[i].getModifiers()));  
  33.         }  
  34.           
  35.     }  
  36.     public static void main(String[] args) {  
  37.           
  38.         //獲得類的修飾符  
  39.         UserInfo ui =new UserInfo();  
  40.         System.out.println("獲得這個類的修飾符:"+GetModifiers.useModifiers(ui)+"\n");  
  41.           
  42.         //獲得本類屬性的修飾符  
  43.         GetModifiers gm = new GetModifiers();  
  44.         gm.checkThisClassModifiers();  
  45.           
  46.     }  
  47.   
  48. }  
運行結果:

獲得這個類的修飾符:public

 

第1個屬性的修飾符為:private

第2個屬性的修飾符為:

第3個屬性的修飾符為:public static final      



實例五:獲得類的構造函數

[java]  view plain copy 在CODE上查看代碼片 派生到我的代碼片
  1. package reflection.getconstructor;  
  2.   
  3. import java.lang.reflect.Constructor;  
  4.   
  5. //獲得類的構造函數  
  6. public class GetConstructor {  
  7.   
  8.     //構造函數一  
  9.     GetConstructor(int a) {  
  10.           
  11.     }  
  12.       
  13.     //構造函數二  
  14.     GetConstructor(int a, String b) {  
  15.           
  16.     }  
  17.       
  18.     public static void getConstructorInfo(String className) {  
  19.         try {  
  20.             //獲得類的對象  
  21.             Class cl =Class.forName(className);  
  22.             System.out.println("獲得類"+className+"所有的構造函數");  
  23.             Constructor ctorlist[] = cl.getDeclaredConstructors();  
  24.             System.out.println("遍歷構造函數\n");  
  25.             for(int i =0 ; i<ctorlist.length; i++)  
  26.             {  
  27.                 Constructor con = ctorlist[i];  
  28.                 System.out.println("這個構造函數的名字為:"+con.getName());  
  29.                 System.out.println("通過構造函數獲得這個類的名字為:"+con.getDeclaringClass());  
  30.                   
  31.                 Class cp[] = con.getParameterTypes();  
  32.                 for (int j=0; j<cp.length; j++)  
  33.                 {  
  34.                     System.out.println("參數 "+j+" 為 "+cp[j]+"\n");  
  35.                 }  
  36.             }  
  37.         }catch (Exception e) {  
  38.                 System.err.println(e);            
  39.         }  
  40.     }  
  41.     public static void main(String[] args) {  
  42.         GetConstructor.getConstructorInfo("reflection.getconstructor.GetConstructor");  
  43.     }  
  44.   
  45. }  

運行結果:

獲得類reflection.getconstructor.GetConstructor所有的構造函數

遍歷構造函數

 

這個構造函數的名字為:reflection.getconstructor.GetConstructor

通過構造函數獲得這個類的名字為:class reflection.getconstructor.GetConstructor       

參數 0 為 int

 

這個構造函數的名字為:reflection.getconstructor.GetConstructor

通過構造函數獲得這個類的名字為:class reflection.getconstructor.GetConstructor

參數 0 為 int

 

參數 1 為 class java.lang.String



實例六:獲得父類

[java]  view plain copy 在CODE上查看代碼片 派生到我的代碼片
  1. package reflection.getparentclass;  
  2.   
  3. //獲得父類  
  4. public class GetParentClass {  
  5.   
  6.     public static String getParentClass(UserInfoMore uim) {  
  7.           
  8.         //獲得父類  
  9.         Class uimc = uim.getClass().getSuperclass();  
  10.         System.out.println("獲得父類的名字為:"+uimc.getName());  
  11.         return uimc.getName();  
  12.           
  13.     }  
  14.       
  15.     public static void searchParentClass() {  
  16.           
  17.     }  
  18.       
  19.     public static void main(String[] args) {  
  20.           
  21.         UserInfoMore uim = new UserInfoMore();  
  22.         System.out.println("成功獲得UserInfoMore的父類:"+GetParentClass.getParentClass(uim));  
  23.           
  24.     }  
  25.   
  26. }  

運行結果:

獲得父類的名字為:reflection.UserInfo

成功獲得UserInfoMore的父類:reflection.UserInfo   



實例七:獲得類的方法

[java]  view plain copy 在CODE上查看代碼片 派生到我的代碼片
  1. package reflection.getmethod;  
  2.   
  3. import java.lang.reflect.Method;  
  4.   
  5. //獲得類的方法  
  6. public class GetMethod {  
  7.   
  8.     public static void getMethods(String className) {  
  9.         try {  
  10.             System.out.println("開始遍歷類"+className+".class");  
  11.             //獲得類名  
  12.             Class cls = Class.forName(className);  
  13.             //利用方法獲得所有該類的方法  
  14.             System.out.println("利用類的getDeclaredMethods獲得類的所有方法");  
  15.             Method ml[] =cls.getDeclaredMethods();  
  16.             System.out.println("遍歷獲得的方法數組\n");  
  17.             for (int i = 0 ;i<ml.length;i++)  
  18.             {  
  19.                 System.out.println("開始遍歷第"+(i+1)+"個方法");  
  20.                 Method m = ml[i];  
  21.                 System.out.println("開始獲取方法的變量類型");  
  22.                 Class ptype[] = m.getParameterTypes();  
  23.                 for (int j=0; j<ptype.length; j++)  
  24.                 {  
  25.                     System.out.println("方法參數"+j+"類型為"+ptype[j]);  
  26.                 }  
  27.                 Class gEx[] = m.getExceptionTypes();  
  28.                 for (int j=0 ; j<gEx.length; j++)  
  29.                 {  
  30.                     System.out.println("異常"+j+"為"+ gEx[j]);  
  31.                 }  
  32.                   
  33.                 System.out.println("該方法的返回值類型為:"+m.getReturnType()+"\n");  
  34.                   
  35.             }  
  36.         }catch (Exception e) {  
  37.             e.printStackTrace();  
  38.         }  
  39.     }  
  40.       
  41.     public static void main(String[] args) {  
  42.         GetMethod.getMethods("reflection.UserInfo");  
  43.     }  
  44.   
  45. }  

運行結果:

開始遍歷類reflection.UserInfo.class

利用類的getDeclaredMethods獲得類的所有方法         

遍歷獲得的方法數組

 

開始遍歷第1個方法

開始獲取方法的變量類型

該方法的返回值類型為:class java.lang.String

 

開始遍歷第2個方法

開始獲取方法的變量類型

該方法的返回值類型為:class java.lang.Integer

 

開始遍歷第3個方法

開始獲取方法的變量類型

方法參數0類型為class java.lang.String

該方法的返回值類型為:void

 

開始遍歷第4個方法

開始獲取方法的變量類型

該方法的返回值類型為:class java.lang.String

 

開始遍歷第5個方法

開始獲取方法的變量類型

方法參數0類型為class java.lang.Integer

該方法的返回值類型為:void

 

開始遍歷第6個方法

開始獲取方法的變量類型

該方法的返回值類型為:class java.lang.String

 

開始遍歷第7個方法

開始獲取方法的變量類型

方法參數0類型為class java.lang.String

該方法的返回值類型為:void

 


這次實例不少吧,而且這些小例子都比較簡單,相信大家都可以輕松秒懂。上面一些例子的代碼並不是完整的,有些只有一些關鍵代碼,如果想要完整的代碼請戳下面的鏈接。最后祝大家學習愉快!


轉自http://blog.csdn.net/liushuijinger/article/details/14223459

http://blog.csdn.net/liushuijinger/article/details/15378475


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM