类加载与反射

类加载

class类

java.lang.Class类封装一个对象和接口运行时的状态。

当加载类时Class类型的对象将自动创建,通过Class对象就可以访问JVM中类的所有信息。

Class类没有公共构造方法,其对象是JVM在加载类时通过类加载器中的defineClass()方法自动构造的,因此不能显式地构造一个Class对象。

可以获取所有构造方法,方法,变量,内部类,外部类,对应类的修饰符,并且判断类型。

获取Class对象有三种方法:

  1. Class.forName(“所需类的全限定类名”)
  2. 调用某个类的class方法 Float.class
  3. 调用某个对象的getClass()方法 a.getClass()

类加载步骤

当程序主动使用某个类时,如果该类还未被加载到内存中,系统将通过加载,连接和初始化三个步骤对类进行初始化。

类加载器

类加载器负责将磁盘或者网络上的.class文件加载到内存中,并为之生成对应的java.lang.Class对象

类加载器负责加载所有的类,JVM启动时,会形成由三个类加载器组成的初始类加载器层次结构:

  • Bootstrap ClassLoader:根类加载器,负责加载Java的核心类库
  • Extension ClassLoader:扩展类加载器,负责加载JRE的扩展目录中的jar包
  • System ClassLoader:系统类加载器,负责在JVM启动时加载来自Java命令的-classpath选项,java.class.path系统属性,或CLASSPATH环境变量所指定的jar包和类路径
  • 用户也可以自定义加载器
    1
    2
    3
    4
    5
    6
    7
    根类加载器
    |
    扩展类加载器
    |
    系统类加载器
    |
    用户类加载器

tips:类加载机制:全盘负责,父类委托,缓存机制

ClassLoader类

java.lang.ClassLoader是一个抽象类,通过继承ClassLoader类来实现自定义的用户类加载器,重写方法
实现自定义的类加载器可以通过重写ClassLoader类的loadClass()或findClass()方法来实现。推荐重写findClass()避免覆盖默认类加载器的父类委托,缓冲机制两种策略

反射

java中有许多对象在运行时都会出现两种类型:编译时类型和运行时类型,

某些情况下程序会在运行时接收到外部传入的一个对象,该对象的编译时类型和运行时类型不同,
但程序需要调用该对象运行时类型的方法,在无法预知该对象属于哪些类的情况下,必须通过反射来发现该对象和类的真实信息。

反射机制允许程序在运行时借助Reflection API取得任何类的内部信息,并能直接操作对象的内部属性和方法。反射被视为动态语言的关键。

java反射机制主要提供了以下功能:

  • 在运行时判断任意一个对象所属的类
  • 在运行时构造任意一个类的对象
  • 在运行时获取任意一个类所具有的成员变量和方法
  • 在运行时调用任意一个对象的方法
  • 生成动态代理

Reflection API提供了Constructor,Field和Method类,这三个类定义在java.lang.reflect包中,分别用于描述类的构造方法,属性和方法

java.lang.reflect包下的Executable抽象类,该对象代表可执行的类成员。
Executable抽象类派生了Constructor和Method两个子类。

Executable抽象类提供了大量方法来获取参数,修饰符或注解等信息

Executable方法列表

方法 功能描述
Parameter[] getParameters() 获取所有形参,返回一个Parameter[]数组
int getParameterCount() 获取形参个数
abstract int getModifiers 获取修饰符,返回的整数是修饰符所对应的常量
boolean isVarArgs() 判断是否包含数量可变的形参

Constructor类用于表示类的构造方法,通过调用Class对象的getConstructor()方法可以获取当前类的构造方法的集合

Constructor类方法列表

方法 功能描述
String getName() 返回构造方法的名称
Class[] getParameterTypes() 返回当前构造方法的参数类型
int getModifiers() 返回修饰符的整型标识,返回的整数是修饰符public,protected,private,final,static,abstract等关键字所对应的常量,需要使用Modifier工具类的方法解码后才能获得真实的修饰符

Method类用于封装方法的信息,调用Class对象的getMethods()方法或getMethod()可以获取当前类的所有方法或指定方法
Method类常用方法

方法 功能描述
String getName() 返回方法的名称
Class[] getParameterTypes() 返回当前方法的参数类型
int getModifiers() 返回修饰符的整型标识
Class getReturnType() 返回当前方法的返回类型

Field类用于封装属性的信息,调用Class对象的getFields()或getField()方法可以获得当前类的所有属性或指定属性。

Field类常用方法

方法 功能描述
String getName() 返回属性的名称
int getModifiers() 返回修饰符的整型标识
getXxx(Object obj) 获取属性的值,此处的Xxx对应java中基本类型;如果属性是引用类型,则直接使用get(Object obj)
setXxx(Object obj,Xxx val) 设置属性值;set(Object obj,Object val)
Class [] getType() 返回当前属性的类型

Parameter类,每个Parameter对象代表方法的一个参数。Parameter类中提供了许多方法来获取参数信息。

Parameter类常用方法

方法 功能描述
int getModifiers() 获取参数的修饰符
String getName() 获取参数的形参名
Type getParameterizedType() 获取带泛型的形参类型
Class<?>getType() 获取形参类型
boolean isVarArgs() 判断该参数是否是可变参数
boolean isNamePresent() 判断.class文件中是否包含方法的形参名信息

类加载与反射
https://shanhainanhua.github.io/2019/09/15/类加载与反射/
作者
wantong
发布于
2019年9月15日
许可协议