Java反射

简介

反射步骤

  1. 获取当前线程的上下文类加载器去加载类文件,此时会在方法区生成类的元信息Class对象,保存在类的各种信息,构造函数,成员方法,静态方法,实例域,静态域,类加载器等等信息
  2. 通过Class对象获取类的构造函数Constructor对象,然后调用newInstance方法即可生成一个实例对象
  3. 然后可以通过Class对象获取类的方法Method对象,调用Method对象的invoke方法即可达到反射调用对象方法的效果

本质上为程序员主动加载类,在方法区生成Class对象,然后调用Class的方法可以反射获取类的各种信息,通过这些信息可以反射调用类的各种方法,达到动态操作对象的目的

类装载器ClassLoader

查找类的字节码文件并构造出类在JVM内部表示对象的组件,其中类加载器加载类到JVM中需要经过以下步骤:

  • 装载:查找和导入Class文件
  • 链接:验证、准备(给类的静态变量分配存储空间)、解析
  • 初始化:对类的静态变量、静态代码块执行初始化工作

装载工作由类加载器负责,其他工作由JVM负责

有三个类装载器:
根装载器:装载JRE的核心类库
ExtClassLoader(扩展类装载器):装载JRE扩展目录ext中的JAR包
AppClassLoader(应用类装载器):装载Classpath路径下的类包

经验所得:
在开发过程中遇到java.lang.NoSuchMethodError错误,究其根源基本是由JVM的双亲委派机制引起的。类路径下放置了多个不同版本的类包,代码中用到了高版本的某个方法,而这个方法在低版本中不存在,JVM加载器加载了低版本的类包,运行时就会报错

类文件被装载并解析后,在JVM内部有一个对应的Class类描述对象,该类的实例有一个指向该Class对象的引用,而Class对象又有指向关联ClassLoader的引用
Java反射

每个类在JVM中都有一个对应的java.lang.Class对象,它提供了类的结构信息的描述,数组、基本类型、枚举、注解甚至void都有对应的Class对象。Class没有public的构造函数方法。Class对象是在装载类的时候JVM调用类装载器中的defineClass()方法自动构造的。

反射访问private和protected成员变量或者方法时,必须通过setAccessible(boolean access)方法取消Java语言检查,否则抛出异常,如果JVM的安全管理器设置了相应的安全机制,那么调用该方法将抛出SecurityException异常