欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Java中的反射机制

程序员文章站 2022-06-03 18:09:20
Android开发中的热修复涉及到反射及类的加载等,因此先回顾一下java的反射,关于反射的定义及作用等引用博客“https://blog.csdn.net/qq_38371934/article/details/81071881”中的话。 说明:上述链接的标题四中的第【8】条描述有误,已经在留言中 ......

  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