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);
五、反射的例子
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 */
重點說明一下方法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
