Java中的反射机制

2019-08-09 00:00:00 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(),然后再创建实例。

《Java中的反射机制》
《Java中的反射机制》

 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

 

五、反射的例子

《Java中的反射机制》
《Java中的反射机制》

  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 */

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.
     */

六、参考文章:

1、https://blog.csdn.net/qq_38371934/article/details/81071881

2、https://www.cnblogs.com/Eason-S/p/5851078.html

 

相关文章