1、反射的基础:Class
在程序运行期间,Java运行时系统始终为所有的对象维护一个被称为运行时的类型标识。这个信息保存着每个对象所属的类足迹。虚拟机利用运行时信息选择相应的方法执行。然而,可以通过专门的Java类访问这些信息。保存这些信息的类称为Class,泛型形式为Class。Class是反射机制的基础,反射API通过操作Class来获取其完整结构。
获取Class的常用方式:
调用getClass()(Object类中的getClass()方法返回一个Class类型的实例) | Boolean var1 = true;Class classType2 = var1.getClass();System.out.println(classType2);输出:class java.lang.Boolean |
运用T.class 语法(T是任意的Java类型) | Class classType4 = Boolean.class;System.out.println(classType4);输出:class java.lang.Boolean |
运用static method Class.forName()(使用时应该提供异常处理器) | Class classType5 = Class.forName("java.lang.Boolean");System.out.println(classType5);输出:class java.lang.Boolean |
运用primitive wrapper classes的TYPE 语法(这里返回的是原生类型,和Boolean.class返回的不同) |
注:一个Class对象实际上表示的是一个类型,而这个类型未必一定是一种类。例如,int不是类,但int.class是一个Class类型的对象。虚拟机为每个类型管理一个Class对象。因此,可以用==运算符实现两个类对象比较的操作。
Class常用的方法:
方法 | 说明 | 例子 |
getName() | 返回类的名字 | String.class.getName(); 返回: "java.lang.String" |
newInstance() | 快速地创建一个类的实例(调用默认构造器,如果该类没有默认构造器,抛出异常)(如果要为构造器提供参数,使java.lang.reflect.Constructor中的newInstance方法) | String s = "java.util.Date"; Object m = Class.forName(s).newInstance(); |
getSuperclass() | 返回超类 | |
getFields() getMethods() getConstructors()(还有带字符串参数,给定名称的形式) | 分别返回类支持的public域、方法和构造器数组,其中包括超类的公有成员 | |
getDeclaredFields() getDeclaredMethods() getDeclaredConstructors()(还有给定名称的形式) | 分别返回类中声明的全部域、方法和构造器数组。其中包括私有和保护成员,但不包括超类的成员 |
2、使用反射分析类
一个类主要由修饰符,域,构造器,方法组成,而 Field、Method、Constructor类,分别用于描述类的域、方法和构造器。另外java.lang.reflect包中的Modifier类可以分析访问修饰符。那么用它们就可以分析类。
分析类常用的方法:
类 | 方法 | 作用 |
Field Method Constructor | Class getDeclaringClass() | 返回一个用于描述类中定义的构造器、方法或域的Class对象 |
String getName() | 返回相应条目的名称 | |
int getModifiers() | 返回整型数值,用不同的位开关描述访问修饰符的使用状况 | |
Method Constructor | Class[] getExceptionTypes() | 返回一个用于描述方法抛出的异常类型的Class对象数组 |
Class[] getParameterTypes() | 返回一个用于描述参数类型的Class对象数组 | |
Field | Class getType() | 用于返回描述域所属类型的Class类型对象 |
Modifier | static String toString(int modifiers) | 返回对应modifiers位设置的修饰符的字符串表示 |
Static boolean isXXX(int modifiers) | 检测方法名中对应的修饰符在modifiers中的值 |
访问权限问题:
由于反射机制的默认行为受限于Java的访问控制,比如,访问私有的方法,字段,除非拥有访问权限,否则Java安全机制允许查看任意对象有哪些域,而不允许读它们的值(读取将抛异常)。然而如果一个Java程序没有受到安全管理器的控制,就可以覆盖访问控制。为了达到这个目的,就需要调用Field、Method、Constructor对象的setAccessible()方法。
函数 | 作用 |
void setAccessible(boolean flag) | 为反射对象设置可访问标志,flag为true表明屏蔽Java语言的访问检查,使得对象的私有属性也可以被查询和设置 |
boolean isAccessible() | 返回反射对象的可访问标志的值 |
static void setAccessible(AccessibleObject[] array, boolean flag) | 一种设置对象数组可访问标志的快捷方法 |