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 packagecom.test.pattern;2
3 importjava.lang.reflect.Constructor;4 importjava.lang.reflect.Field;5 importjava.lang.reflect.Method;6 importjava.util.Collection;7
8 public class TestReflect extendsObject{9
10 /**
11 *@paramargs12 */
13 public static voidmain(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 interfaceParent{72 //public static final
73 String pName = "inter";74
75 voidmethodInter();76 }77
78 class Child implementsParent{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 @Override95 public voidmethodInter() {96 //TODO Auto-generated method stub
97 System.out.println("print_pName: " +pName);98 }99
100 privateString childMethod(){101 String m = "method_of_child " +cName;102 returnm;103 }104
105 }106
107
108 //运行结果:
109 /*
110
111 ---------mClass.getDeclaredFields():---------112 2 name: cName type: class java.lang.String113 1 name: pro type: class java.lang.String114 0 name: def type: class java.lang.String115 1 name: count type: int116
117 --------- mClass.getFields(): ---------//注意点118 1 name: pro type: class java.lang.String119 1 name: count type: int120 25 name: pName type: class java.lang.String121
122 --------- mClass.getDeclaredMethods()---------123 obj: method_of_child use_in_reflect124
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.
*/
六、参考文章: