一、Java反射机制的理解

反射(Reflection)是Java语言中的一项重要功能,通过反射API可以获取程序在运行时Java类的内部结构,实现对Java代码的动态操作,在实际项目开发中其多要用于框架的构建,一般开发中较少使用,但研究理解是非常必要的。

二、Java反射机制的使用

反射机制的实现主要依赖于Class类和java.lang.reflect.*包中提供的类。通过这些类可以实现对象的创建,类方法的访问等。

(一)Class对象的获取

Class类的构造方法为私有方法,只能由jvm虚拟机在运行时生成,用来保存实例对象的相关信息。获得一个实例对象对应的Class对象,主要有三种方法:

  1. 通过实例变量的getClass()方法,这种方法是获取效率最高和最安全的方式。

    1
    2
    Test test = new Test();
    Class cls = test.getClass();
  2. 通过Class.forName()静态方法获取,这种方法是常用的一种方法,它通过输入的类名查找得到。

    1
    Class t = Class.forName("java.lang.Thread");
  3. 直接给出类文件的Class。

    1
    Class cls = Test.class;

(二)Class对象的使用

  1. 构造方法的获取和使用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    /*
    * getConstructors可以获取声明为public的构造方法的集合,
    * getDeclaredConstructors()方法获取所有的构造方法集合
    */
    Constructor[] constructors = cls.getConstructors();
    // 根据构造方法参数的类型获取对应的构造方法
    Constructor constructor = cls.getConstructor(String.class);
    for(Constructor con:constructors){
    // 构造方法的名称
    String name = con.getName();
    // 构造方法的参数类型
    Class[] type = con.getParameterTypes();
    }
    // 创建新的实例
    Object obj = constructor.newInstance();
  2. 字段获取

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    /*
    * 获取public字段集合
    * getDeclaredFields()获取所有的字段
    */
    Field[] fields = cls.getFields();
    // 字段名称
    String name = field.getName();
    // 字段类型
    Class type = field.getType();
    // 获取静态字段的值
    Object obj = field.get(Object);
  3. 方法获取和执行

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    /*
    * 获取该类的所有方法,包括父类的方法
    * getDeclaredMethods()获取该类的方法,不包括父类方法
    */
    Method[] methods = cls.getMethods();
    // 方法返回值类型
    Class retType = method.getReturnType();
    // 方法名称
    String name = method.getName();
    // 方法类型
    String modifiers = Modifier.toString(method.getModifiers());
    // 方法参数类型
    Class[] paramTypes = method.getParameterTypes();
    /*
    * 调用获取到的方法执行
    * one:对象的实例
    * two:方法参数的集合
    */
    method.invoke(one,two);
  4. 对类的私有域和方法的使用

    类中的私有构造函数、方法和字段,通过相关的方法都可以获取到,但是在使用时确是禁止的,会抛出IllegalAccessException的异常。这是因为反射行为默认是受到Java访问的限制的,如果需要突破限制去访问控制,就需要调用Constructor、Method和Field的公共超类方法setAccessible(),设置为true时反射进制运行时会屏蔽Java语言的访问时检查。

    在实际开发中,有时需要对隐藏的API进行使用时,通过这种机制就可以达到我们的目的。

反射机制的功能十分强大,在运行时可以获取类的结构,分析对象,调用任意的方法。但是由于反射的运行都是在运行时,在编译器会错过很多的检查,不规范的使用反射会提高程序的出错率。而且其运行时需要遍历搜寻的特点,使得使用反射执行方法的速度要慢于直接调用方法。所以一般情况下,应根据实际情况尽量减少使用反射。