Java中的反射機制


  Android開發中的熱修復涉及到反射及類的加載等,因此先回顧一下java的反射,關於反射的定義及作用等引用博客“https://www.cnblogs.com/Eason-S/p/5851078.html”中的話。

  說明:上述鏈接的標題四中的第【8】條描述有誤,已經在留言中指出,詳情也可查看本文“反射的例子”的標注說明。

一、Java反射機制:
      主要是指程序可以訪問,檢測和修改它本身狀態或行為的一種能力,並能根據自身行為的狀態和結果,調整或修改應用所描述行為的狀態和相關的語義。在java中,只要【給定類的名字】, 那么就可以通過反射機制來獲得類的所有信息。   

二、作用:
1、在運行時判斷任意一個對象所屬的類;
2、在運行時獲取類的對象;
3、在運行時訪問java對象的屬性,方法,構造方法等。

三、優缺點:
優點:
1、可以實現動態創建對象和編譯,體現出很大的靈活性。
2、對於JAVA這種先編譯再運行的語言來說,反射機制可以使代碼更加靈活,更加容易實現面向對象。

缺點:
1、對性能有影響。使用反射基本上是一種解釋操作,我們可以告訴JVM,我們希望做什么並且它滿足我們的要求。這類操作總是慢於只直接執行相同的操作。

四、反射的應用場景:

1、該類的某個方法是在高版本新增的,例如MediaRecorder.java在Android6.0以后新增了resume()方法用於暫停后的再次錄制,此時項目為了兼容低版本則可以判斷當版本>=6.0時調用該
方法,但是為了能在6.0以下的開發環境中編譯通過,可以使用反射調用該方法。----------僅作為例子說明,實際開發中編譯環境一般都會超過6.0。

2、關於Handler機制中消息的同步分隔欄,需要通過postSyncBarrier()設置:該方法屬於隱藏方法hide在API23之前,該方法需要通過Looper調用;從API23開始,源碼去掉了Looper中的方法,此時只能通過MessageQueue調用;但無論上述哪種,都需要通過反射調用;

例如:MessageQueue類只有帶參的構造函數,因此需要先getDeclaredConstructor(),然后再創建實例。

 1 //方式一:
 2             Class<?> looperCls = Class.forName("android.os.MessageQueue");
 3             Constructor<?>  constructor = looperCls.getDeclaredConstructor(boolean.class);
 4             constructor.setAccessible(true);        //設置可訪問
 5             
 6             Method method = looperCls.getMethod("postSyncBarrier");
 7             method.invoke(constructor.newInstance(true));  //根據帶參的構造函數創建實例並調用
 8 
 9 postSyncBarrier函數
10             
11 
12 //方式二:
13             Looper looper = getMainLooper();
14             MessageQueue queue = looper.getQueue();
15             Method  methodSync = queue.getClass().getMethod("postSyncBarrier");
16             methodSync.invoke(queue);
View Code

 

五、反射的例子

  1 package com.test.pattern;
  2 
  3 import java.lang.reflect.Constructor;
  4 import java.lang.reflect.Field;
  5 import java.lang.reflect.Method;
  6 import java.util.Collection;
  7 
  8 public class TestReflect extends Object{
  9 
 10     /**
 11      * @param args
 12      */
 13     public static void main(String[] args) {
 14         // TODO Auto-generated method stub
 15         try {
 16             Class<?> mClass = Class.forName("com.test.pattern.Child");
 17             
 18             Field[] childFields = mClass.getDeclaredFields();
 19             
 20             System.out.println("---------mClass.getDeclaredFields():--------- ");
 21             
 22             for (Field field : childFields) {
 23                 int mod = field.getModifiers();  
 24                 Class<?> type = field.getType();
 25                 String name = field.getName();
 26                 
 27                 System.out.println(mod + "  name: " + name + "  type: " + type);
 28             }
 29             
 30             System.out.println("\n--------- mClass.getFields(): ---------");
 31             
 32             Field[] fields = mClass.getFields();   //注意點
 33             
 34             for (Field field : fields) {
 35                 int mod = field.getModifiers();  
 36                 Class<?> type = field.getType();
 37                 String name = field.getName();
 38                 
 39                 System.out.println(mod + "  name: " + name + "  type: " + type);
 40             }
 41             
 42             System.out.println("\n--------- mClass.getDeclaredMethods()---------");
 43             
 44             Method[] methods = mClass.getDeclaredMethods();
 45             for (Method method : methods) {
 46                 try {
 47                     
 48                     if("childMethod".equals(method.getName())){
 49                         method.setAccessible(true);   //設置可訪問-------
 50                         Constructor<?>  constructor = mClass.getDeclaredConstructor(String.class);
 51                         Object obj = method.invoke(constructor.newInstance("use_in_reflect"));
 52                         System.out.println("obj: " + obj);
 53                     }
 54                     
 55                 } catch (Exception e) {
 56                     // TODO Auto-generated catch block
 57                     e.printStackTrace();
 58                 }
 59             }
 60             
 61         } catch (ClassNotFoundException e) {
 62             e.printStackTrace();
 63         }
 64         
 65     }
 66     
 67     
 68 }
 69 
 70 
 71 interface Parent{
 72     //public static final
 73     String pName = "inter";
 74     
 75     void methodInter();
 76 }
 77 
 78 class Child implements Parent{
 79     
 80     private String cName = "childName";
 81     
 82     public String pro = "pro";        //注意點
 83     
 84     String def = "default";
 85     
 86     public int count = 10;            //注意點
 87     
 88     Child(String name) {
 89         // TODO Auto-generated constructor stub
 90         this.cName = name ;
 91     }
 92     
 93 
 94     @Override
 95     public void methodInter() {
 96         // TODO Auto-generated method stub
 97         System.out.println("print_pName: " + pName);
 98     }
 99     
100     private String childMethod(){
101         String m = "method_of_child " + cName;
102         return m;
103     }
104     
105 }
106 
107 
108 //運行結果:
109 /*
110 
111 ---------mClass.getDeclaredFields():--------- 
112 2  name: cName  type: class java.lang.String
113 1  name: pro  type: class java.lang.String
114 0  name: def  type: class java.lang.String
115 1  name: count  type: int
116 
117 --------- mClass.getFields(): ---------//注意點
118 1  name: pro  type: class java.lang.String
119 1  name: count  type: int
120 25  name: pName  type: class java.lang.String
121 
122 --------- mClass.getDeclaredMethods()---------
123 obj: method_of_child use_in_reflect
124 
125 */
View Code

重點說明一下方法getFields():獲取公有屬性,即獲取的不僅僅是父類屬性,還包括類本身public類型的屬性。看“注意點”的運行結果即可知道。

官方介紹:
    /* Returns an array containing {@code Field} objects reflecting all
     * the accessible public fields of the class or interface represented by
     * this {@code Class} object.
     */

六、參考文章:

1、https://blog.csdn.net/qq_38371934/article/details/81071881

2、https://www.cnblogs.com/Eason-S/p/5851078.html

 


免責聲明!

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



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