Android之反射机制

1.疑问

在进行Android应用编写的过程中,常常听到专业术语"反射机制",是否也有同样的以下几点疑问
  • A. 反射机制是什么?
  • B. 反射机制能带来什么好处?
  • C. 反射机制怎么使用?具体有什么方法?
2.Java的编译运行过程
在了解反射机制前,我们先了解下JAVA的编译运行过程,也就是经常提到的一次编译到处执行,如下:
  • .java的源代码文件被编译成.class文件字节码
  • JVM中的类加载器加载各个类.class字节码文件
  • 加载完毕之后,字节码在JAVA虚拟机JVM中执行
例如:
Class类的对象表示正在运行的Java程序中的类或接口,也就是任何一个类被加载时,即将类的.class文件(字节码文件)读入内存的同时,都自动为之创建一个java.lang.Class对象。
Class类没有公共构造方法,其对象是JVM在加载类时通过调用类加载器中的defineClass()方法创建的
3.Java反射机制
在了解JAVA编译运行过程后,下面我们来看看对于开篇提到的反射机制的几个问题
  • A. 反射机制是什么?
反射机制就是对编译后的.class字节码进行解剖,解剖出方法(构造方法等),成员变量、修饰符等,在解剖先加载相关类的字节
  • B. 反射机制能带来什么好处?
因为通过编译后的.class文件仅有public方法,对于隐藏的方法及静态修饰的变脸或方法,可以使用反射机制调用,从而可以更快捷的实现功能
  • C. 反射机制怎么使用?具体有什么方法?
关于反射机制具体如何使用及具体的方法,先了解以下相关内容,在最后章节中举例说明
3.1 获取类的对象
Java中,每个class都有一个相应的Class对象。也就是说,当我们编写一个类,编译完成后,在生成的.class文件中,就会产生一个Class对象,用于表示这个类的类型信息。
反射机制获取类的对象三种方法:
  • 通过forName方法获取
Class c = Class.forName("类名")

  • 通过class属性获取
Class c = 类名.class

  • 通过getClass属性获取
类名 对象=new 类名() Class c = 对象.getClass

3.2 获取类的变量(成员变量)
Field类
3.3 获取类的方法
Method类:代表类的方法
  • 获取所有的方法
getDeclaredMethods() getDeclaredMethod("方法名",参数类型.class,……)

  • 获得方法的放回类型
getReturnType()

  • 获得方法的传入参数类型
getParameterTypes()

3.4 获取构造方法
Constructor类:代表类的构造方法
  • 获取所有的构造方法
getDeclaredConstructors()

  • 获取特定的构造方法
getDeclaredConstructor(参数类型.class,……)

4.举例
长按关机键关机,shutdown方法,通过源码发现,此方法为隐藏hide方法
【Android之反射机制】Android之反射机制
文章图片

如果要使用此方法,则必须使用反射机制
PowerManager powerManager = (PowerManager)getSystemService(POWER_SERVICE); Class c =powerManager.getClass(); try { Method m = c.getMethod("shutdown",boolean.class,String.class,boolean.class); m.invoke(powerManager,confirm,wait,false); } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { e.printStackTrace(); }

4.1 反射机制实现:
代码段如下
public void shutdown(boolean confirm, boolean wait) throws RemoteException { PowerManager powerManager = (PowerManager)getSystemService(POWER_SERVICE); Class c =powerManager.getClass(); try { Method m = c.getMethod("shutdown",boolean.class,String.class,boolean.class); m.invoke(powerManager,confirm,wait,false); } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { e.printStackTrace(); } }

  • step1
加载相应类,即获取运行时类对象
Class c =powerManager.getClass();

  • step2
获取shutdown方法,有三个参数,分别为boolean/string/boolean类型,getMethod的第一个参数为方法名
Method m = c.getMethod("shutdown",boolean.class,String.class,boolean.class);

  • step3
最后使用invoke方法进行反射,其中invoke的第一个参数为对象,后面的参数为具体的参数
m.invoke(powerManager,confirm,wait,false);

    推荐阅读