1. 程式人生 > >Java經典反射例項

Java經典反射例項

Java提供了一套機制來動態執行方法和構造方法,以及陣列操作等,這套機制就叫——反射。反射機制是如今很多流行框架的實現基礎,其中包括Spring、Hibernate等。原理性的問題不是本文的重點,接下來讓我們在例項中學習這套精彩的機制。

1. 得到某個物件的屬性

Java程式碼 複製程式碼
  1. public Object getProperty(Object owner, String fieldName) throws Exception {         
  2.     Class ownerClass = owner.getClass();                                             
  3.     Field field = ownerClass.getField(fieldName);                                    
  4.     Object property = field.get(owner);                                              
  5.     return property;                                                                 
  6. }        
public Object getProperty(Object owner, String fieldName) throws Exception {       
    Class ownerClass = owner.getClass();                                           
                                                                                   
    Field field = ownerClass.getField(fieldName);                                  
                                                                                   
    Object property = field.get(owner);                                            
                                                                                   
    return property;                                                               
}      

Class ownerClass = owner.getClass():得到該物件的Class。

Field field = ownerClass.getField(fieldName):通過Class得到類宣告的屬性。

Object property = field.get(owner):通過物件得到該屬性的例項,如果這個屬性是非公有的,這裡會報IllegalAccessException。
2. 得到某個類的靜態屬性
Java程式碼 複製程式碼
  1. public Object getStaticProperty(String className, String fieldName)       
  2.             throws
     Exception {                                            
  3.     Class ownerClass = Class.forName(className);                          
  4.     Field field = ownerClass.getField(fieldName);                         
  5.     Object property = field.get(ownerClass);                              
  6.     return property;                                                      
  7. }      
public Object getStaticProperty(String className, String fieldName)     
            throws Exception {                                          
    Class ownerClass = Class.forName(className);                        
                                                                        
    Field field = ownerClass.getField(fieldName);                       
                                                                        
    Object property = field.get(ownerClass);                            
                                                                        
    return property;                                                    
}    

Class ownerClass = Class.forName(className) :首先得到這個類的Class。

Field field = ownerClass.getField(fieldName):和上面一樣,通過Class得到類宣告的屬性。

Object property = field.get(ownerClass) :這裡和上面有些不同,因為該屬性是靜態的,所以直接從類的Class裡取。


3. 執行某物件的方法
Java程式碼 複製程式碼
  1. public Object invokeMethod(Object owner, String methodName, Object[] args) throws Exception {      
  2.     Class ownerClass = owner.getClass();      
  3.     Class[] argsClass = new Class[args.length];      
  4.     for (int i = 0, j = args.length; i < j; i++) {      
  5.         argsClass[i] = args[i].getClass();      
  6.     }       
  7.     Method method = ownerClass.getMethod(methodName, argsClass);         
  8.     return method.invoke(owner, args);       
  9. }     
public Object invokeMethod(Object owner, String methodName, Object[] args) throws Exception {    
    Class ownerClass = owner.getClass();    
    Class[] argsClass = new Class[args.length];    
    for (int i = 0, j = args.length; i < j; i++) {    
        argsClass[i] = args[i].getClass();    
    }     
    Method method = ownerClass.getMethod(methodName, argsClass);       
    return method.invoke(owner, args);     
}   

Class owner_class = owner.getClass() :首先還是必須得到這個物件的Class。

3~6行:配置引數的Class陣列,作為尋找Method的條件。

Method method = ownerClass.getMethod(methodName, argsClass):通過Method名和引數的Class陣列得到要執行的Method。

method.invoke(owner, args):執行該Method,invoke方法的引數是執行這個方法的物件,和引數陣列。返回值是Object,也既是該方法的返回值。


4. 執行某個類的靜態方法
Java程式碼 複製程式碼
  1. public Object invokeStaticMethod(String className, String methodName,               
  2.             Object[] args) throws Exception {                                       
  3.     Class ownerClass = Class.forName(className);                                    
  4.     Class[] argsClass = new Class[args.length];                                     
  5.     for (int i = 0, j = args.length; i < j; i++) {                                  
  6.         argsClass[i] = args[i].getClass();                                          
  7.     }                                                                               
  8.     Method method = ownerClass.getMethod(methodName, argsClass);                    
  9.     return method.invoke(null, args);                                               
  10. }                
public Object invokeStaticMethod(String className, String methodName,             
            Object[] args) throws Exception {                                     
    Class ownerClass = Class.forName(className);                                  
                                                                                  
    Class[] argsClass = new Class[args.length];                                   
                                                                                  
    for (int i = 0, j = args.length; i < j; i++) {                                
        argsClass[i] = args[i].getClass();                                        
    }                                                                             
                                                                                  
    Method method = ownerClass.getMethod(methodName, argsClass);                  
                                                                                  
    return method.invoke(null, args);                                             
}              

基本的原理和例項3相同,不同點是最後一行,invoke的一個引數是null,因為這是靜態方法,不需要藉助例項執行。



5. 新建例項

Java程式碼 複製程式碼
  1. public Object newInstance(String className, Object[] args) throws Exception {       
  2.     Class newoneClass = Class.forName(className);                                   
  3.     Class[] argsClass = new Class[args.length];                                     
  4.     for (int i = 0, j = args.length; i < j; i++) {                                  
  5.         argsClass[i] = args[i].getClass();                                          
  6.     }                                                                               
  7.     Constructor cons = newoneClass.getConstructor(argsClass);                       
  8.     return cons.newInstance(args);                                                  
  9. }    
public Object newInstance(String className, Object[] args) throws Exception {     
    Class newoneClass = Class.forName(className);                                 
                                                                                  
    Class[] argsClass = new Class[args.length];                                   
                                                                                  
    for (int i = 0, j = args.length; i < j; i++) {                                
        argsClass[i] = args[i].getClass();                                        
    }                                                                             
                                                                                  
    Constructor cons = newoneClass.getConstructor(argsClass);                     
                                                                                  
    return cons.newInstance(args);                                                
                                                                                  
}  

這裡說的方法是執行帶引數的建構函式來新建例項的方法。如果不需要引數,可以直接使用newoneClass.newInstance()來實現。

Class newoneClass = Class.forName(className):第一步,得到要構造的例項的Class。

第6~第10行:得到引數的Class陣列。

Constructor cons = newoneClass.getConstructor(argsClass):得到構造子。

cons.newInstance(args):新建例項。


6. 判斷是否為某個類的例項

Java程式碼 複製程式碼
  1. publicboolean isInstance(Object obj, Class cls) {           
  2.     return cls.isInstance(obj);                              
  3. }      
public boolean isInstance(Object obj, Class cls) {         
    return cls.isInstance(obj);                            
}    

7. 得到陣列中的某個元素
Java程式碼 複製程式碼
  1. public Object getByArray(Object array, int index) {          
  2.     return Array.get(array,index);                           
  3. }   
public Object getByArray(Object array, int index) {        
    return Array.get(array,index);                         
} 

附完整原始碼:
Java程式碼 複製程式碼
  1. import java.lang.reflect.Array;      
  2. import java.lang.reflect.Constructor;      
  3. import java.lang.reflect.Field;      
  4. import java.lang.reflect.Method;      
  5. /**    
  6.  * Java Reflection Cookbook    
  7.  *    
  8.  * @author Michael Lee    
  9.  * @since 2006-8-23    
  10.  * @version 0.1a    
  11.  */
  12. publicclass Reflection {      
  13.     /**    
  14.      * 得到某個物件的公共屬性    
  15.      *    
  16.      * @param owner, fieldName    
  17.      * @return 該屬性物件    
  18.      * @throws Exception    
  19.      *    
  20.      */
  21.     public Object getProperty(Object owner, String fieldName) throws Exception {      
  22.         Class ownerClass = owner.getClass();      
  23.         Field field = ownerClass.getField(fieldName);      
  24.         Object property = field.get(owner);      
  25.         return property;      
  26.     }      
  27.     /**    
  28.      * 得到某類的靜態公共屬性    
  29.      *    
  30.      * @param className   類名    
  31.      * @param fieldName   屬性名    
  32.      * @return 該屬性物件    
  33.      * @throws Exception    
  34.      */
  35.     public Object getStaticProperty(String className, String fieldName)      
  36.             throws Exception {      
  37.         Class ownerClass = Class.forName(className);      
  38.         Field field = ownerClass.getField(fieldName);      
  39.         Object property = field.get(ownerClass);      
  40.         return property;      
  41.     }      
  42.     /**    
  43.      * 執行某物件方法    
  44.      *    
  45.      * @param owner    
  46.      *            物件    
  47.      * @param methodName    
  48.      *            方法名    
  49.      * @param args    
  50.      *            引數    
  51.      * @return 方法返回值    
  52.      * @throws Exception    
  53.      */
  54.     public Object invokeMethod(Object owner, String methodName, Object[] args)      
  55.             throws Exception {      
  56.         Class ownerClass = owner.getClass();      
  57.         Class[] argsClass = new Class[args.length];      
  58.         for (int i = 0, j = args.length; i < j; i++) {      
  59.             argsClass[i] = args[i].getClass();      
  60.         }      
  61.         Method method = ownerClass.getMethod(methodName, argsClass);      
  62.         return method.invoke(owner, args);      
  63.     }      
  64.       /**    
  65.      * 執行某類的靜態方法    
  66.      *    
  67.      * @param className    
  68.      *            類名    
  69.      * @param methodName    
  70.      *            方法名    
  71.      * @param args    
  72.      *            引數陣列    
  73.      * @return 執行方法返回的結果    
  74.      * @throws Exception    
  75.      */
  76.     public Object invokeStaticMethod(String className, String methodName,      
  77.             Object[] args) throws Exception {      
  78.         Class ownerClass = Class.forName(className);      
  79.         Class[] argsClass = new Class[args.length];      
  80.         for (int i = 0, j = args.length; i < j; i++) {      
  81.             argsClass[i] = args[i].getClass();      
  82.         }      
  83.         Method method = ownerClass.getMethod(methodName, argsClass);      
  84.         return method.invoke(null, args);      
  85.     }      
  86.     /**    
  87.      * 新建例項    
  88.      *    
  89.      * @param className    
  90.      *            類名    
  91.      * @param args    
  92.      *            建構函式的引數    
  93.      * @return 新建的例項    
  94.      * @throws Exception    
  95.      */
  96.     public Object newInstance(String className, Object[] args) throws Exception {      
  97.         Class newoneClass = Class.forName(className);      
  98.         Class[] argsClass = new Class[args.length];      
  99.         for (int i = 0, j = args.length; i < j; i++) {      
  100.             argsClass[i] = args[i].getClass();      
  101.         }      
  102.         Constructor cons = newoneClass.getConstructor(argsClass);      
  103.         return cons.newInstance(args);      
  104.     }      
  105.     /**    
  106.      * 是不是某個類的例項    
  107.      * @param obj 例項    
  108.      * @param cls 類    
  109.      * @return 如果 obj 是此類的例項,則返回 true    
  110.      */
  111.     publicboolean isInstance(Object obj, Class cls) {      
  112.         return cls.isInstance(obj);      
  113.     }      
  114.     /**    
  115.      * 得到陣列中的某個元素    
  116.      * @param array 陣列    
  117.      * @param index 索引    
  118.      * @return 返回指定陣列物件中索引元件的值    
  119.      */
  120.     public Object getByArray(Object array, int index) {      
  121.         return Array.get(array,index);      
  122.     }      
  123. }