Java中的反射机制
android开发中的热修复涉及到反射及类的加载等,因此先回顾一下java的反射,关于反射的定义及作用等引用博客“https://blog.csdn.net/qq_38371934/article/details/81071881”中的话。
说明:上述链接的标题四中的第【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、
2、https://www.cnblogs.com/eason-s/p/5851078.html
上一篇: 秦始皇在自己墓里放置含剧毒的水银,真实原因是什么?
下一篇: 聪明的泰迪