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);
五、反射的例子
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