首页 > 代码库 > Reflection

Reflection


【概述】所谓的反射,可以理解为在运行时获取对象类型信息的操作。java.lang.Class 类是 Java 反射的起源,针对任何一个想要探测的类,只有先为它产生一个 Class 对象,才能通过 Class 对象获取其他想要的信息。Java 程序在运行时,系统会对所有的对象进行所谓的运行时类型标识,用来保存这些类型信息的类就是 Class 类。Class 类封装一个对象或接口运行时的状态。
【重要】JVM 为每种类型管理着一个独一无二的 Class 对象。也就是说,每个类(型)都有一个 Class 对象。Java 程序运行过程中,当需要创建某个类的实例时,JVM 首先检查所要加载的类对应的 Class 对象是否已经存在。如果还不存在,JVM 就会根据类名查找对应的字节码文件并加载,接着创建对应的 Class 对象,最后才创建出这个类的实例。
【说明】Java 基本数据类型(boolean, byte, char, short, int, long, float, double)和关键字 void 都对应一个 Class 对象。每个数组也对应为一个 Class 对象,所有具有相同类型和维数的数组都共享该 Class 对象。枚举是一种类,注释是一种接口。

    也就是说,运行中的类或接口在 JVM 中都会有一个对应的 Class 对象存在,它保存了对应类或接口的类型信息。要想获取类或接口的相应信息,需要先获取这个 Class 对象,然后调用 Class 对象提供的相应方法来获取。

【常用1】获得 Class 对象的三种方法:
1)调用 Object 类的 getClass() 方法来得到 Class 对象,这也是最常见的产生 Class 对象的方法。

eg:    MyObject x = new MyObject(); 
         Class c1 = x.getClass();

2)使用 Class 类的 forNmae() 静态方法获得与字符串对应的 Class 对象。

eg:    Class c2 = Class.forName("java.lang.String");

3)使用“类型名.class”来获取该类型对应的 Class 对象。

eg:    Class c1 = MyType.class;
         Class c2 = int.class;
         Class c3 = double[].class;

【常用2】Class 类中提供了很多用来获取所代表的实体的信息的方法。注意这个特别的方法:public T newInstance(); 创建此 Class 对象所表示类的一个新实例。使用的是不带参数的构造方法,如果该类没有无参构造方法,在调用 newInstance() 方法时会抛出一个 NoSuchMethodException 异常。

eg:    Class c = Class.forName("java.util.ArrayList");
         List list = (List)c.newInstance();

【常用3】使用反射可以获取指定类的指定方法的对象代表,方法的对象代表即 java.lang.reflect.Method 类的实例,通过 Method 类的 invoke 方法可以动态调用该方法。
        public Object invoke(Object obj, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException
方法的第一个参数是一个对象,表示要在该对象上调用这个方法;第二个参数是一个可变参数,用来给这个方法传递参数值;invoke 方法的返回值用来表示动态调用指定方法后的实际返回值。[注意]:若要通过反射调用类的某个私有方法,可以在这个私有方法对应的 Method 对象上先调用 setAccessible(true) 来取消 Java 语言对本方法的访问检查,然后再调用 invoke 方法来真正执行这个私有方法。
【应用】在实际开发中,为了实现对个各类的解耦,在对类进行调用和实例化时,通常在配置文件中配置相应的类名,在程序中读取类名,然后通过反射技术在程序中进行加载和实例化。例如:数据库驱动程序类,为了达到不依赖特定数据库驱动类,可将用到的数据库驱动类名放到配置文件中(常用的有 XML文件、properties文件、文本文件),然后在程序中加载驱动,来实现对数据库的解耦;也就是说只要修改配置文件,就可以方便地更改数据库类型。
【补充】
1)Java 中的 properties 文件是一种配置文件,主要用于说明配置信息。其文件类型为 *.properties, 格式为文本文件,文件的内容采用“键=值”的格式,也就是说文件的每一行都是先定义一个键名,然后付给他一个值。在 properties 文件中,用“#”来作注释。另请参考 java.util.Properties 类。