14.反射
通过Java的反射机制,可以更深入地控制程序的运行过程,如再程序运行时对用户输入的信息进行验证,还可以逆向控制程序的执行过程。此外Java在反射机制的基础上,还提供了Annotation功能
14.1Class类与Java反射
java.lang.reflect包中提供了对反射的支持,可以在程序中访问已经装载到JVM中的Java对象的描述,实现访问、检测和修改描述Java对象本身信息的功能。
所有java类均继承了Object类,在Object类中定义了一个getClass()方法,该方法返回某类的一个类型为Class的对象,举例如下:
Class textFieldC=textField.getClass(); //textField为JTextField类的对象
利用Class类的对象textFieldC,可以访问用来返回该对象的textField对象的 描述信息,常用的描述星系如下所示:
方法 | 返回值 | 功能描述 |
---|---|---|
getPackage() | Package对象 | 获得该类的存放路径 |
getName() | String对象 | 获得该类的名称 |
getSuperclass() | Class对象 | 获得该类的父类 |
getInterface() | Class型数组 | 获得该类实现的所有接口 |
getConstructors() | Constructor型数组 | 获得所有权限为public的构造方法 |
getConstructor(Class…parameterTypes) | Constructor对象 | 获得权限为public的构造方法 |
getDeclaredConstructors() | Constructor型数组 | 获得所有构造方法,按申明顺序返回 |
getDeclaredConstructor(Class…parameterTypes) | Constructor对象 | 获得指定构造方法 |
getMethods() | Method型数组 | 获得所有权限为public的方法 |
getMethod(String name,Class…parameterTypes) | Method对象 | 获得指定方法 |
getDeclaredMethods() | Method型数组 | 获得所有方法,按申明顺序返回 |
getDeclaredMethods(String name,Class…parameterTypes) | Method对象 | 获得指定方法 |
getFields() | Field型数组 | 获得所有权限为public的成员变量 |
·getField(String name) | Field对象 | 获得权限为public的指定成员变量 |
getDeclaredFields() | Field型数组 | 获得所有权限为public的成员变量 |
getDeclaredField(String name) | Field对象 | 获得指定成员变量 |
getClasses() | Class型数组 | 获得所有权限为public的内部类 |
getDeclaredClass() | Class型对象 | 获得所有内部类 |
getDeclaringClass() | Class对象 | 如果该类为内部类,则返回它的成员类,否则返回null |
getFiled()和getMethods()方法依次获得权限为public的成员变量和方法时,包括从超类中继承到的成员变量和方法;而方法getDeclaredFields()和getDeclaredMethods()只是获得在本类中定义的所有成员变量和方法。
14.1.1访问构造方法
通过下列一组方法访问构造方法时,将返回Constructor类型的对象或者数组,每个Constructor对象代表一个构造方法,利用Constructor对象可以操纵相应构造方法。
getConstructors()
getConstructor(Class
objectClass.getDeclaredConstructor(String.class,int.class)
objectClass.getDeclaredConstructor(new Class[]{String.class,int.class})
Constructor类中提供的常用方法如下表:
方法 | 功能描述 |
---|---|
isVarArgs() | 查看该构造方法是否允许带有可变数量的参数,如果允许则返回true,否则返回false |
getParameterTypes() | 按照声明顺序以Class数组的形式获得该构造方法的各个参数类型 |
getExceptionTypes() | 以Class数组的形式获得该构造方法可能抛出的异常类型 |
newInstance(Obejct..,.initargs) | 通过该构造方法利用指定参数创建一个该类的对象,未设置参数则表示采用默认无参数构造方法 |
setAccessible(bollean flag) | 当构造方法权限为private时,不允许直接使用newInstance(Obejct…initargs)方法创建对象,需要先执行该方法将参数入口设置为true |
getModifiers() | 获得可以解析该构造方法所采用修饰符的参数 |
通过java.lang.reflect.Modifier类可以解析出getMOdifiers()方法的返回值所表示的修饰符信息,在该类中提供了一系列用来解析的静态方法,既可以查看该构造方法是否被指定的修饰符修饰,还可以以字符串的形式获得所有修饰符,该类常用静态方法如下:
静态方法 | 功能描述 |
---|---|
isPublic(int mod) | 查看是否被public修饰符修饰,如果是则返回true,否则返回false |
isProtected(int mod) | 查看是否被protected修饰符修饰,如果是则返回true,否则返回false |
isPrivate(int mod) | 查看是否被private修饰符修饰,如果是则返回true,否则返回false |
isStatic(int mod) | 查看是否被static修饰符修饰,如果是则返回true,否则返回false |
isFinal(int mod) | 查看是否被final修饰符修饰,如果是则返回true,否者返回false |
toString(int mod) | 以字符串的形式返回所有修饰符 |
例如,判断对象constructor所代表的构造方法是否被private修饰,以及以字符串形式获得该构造方法的所有修饰符的典型代码如下:
int modifiers=constructor.getModifiers();
boolean isEmbellishByPrivate=Modifier.isPrivate(modifiers);
String embellishment=Modifier.toString(modifiers);
以下是一个访问构造方法的实例:
以下是一个Example_01类,该类中声明了3个构造方法:
import java.lang.reflect.Constructor;
public class Main_01 {
public static void main(String[] args) {
Example_01 example=new Example_01("10","20","30");
Class<? extends Example_01>exampleC=example.getClass();
//返回一个Example_01类的Class类对象
//泛型中的<?>表示不确定类型
Constructor[]declaredConstructors=exampleC.getDeclaredConstructors();
//获得所有构造方法
for(int i=0;i<declaredConstructors.length;i++){
Constructor<?>constructor=declaredConstructors[i];
System.out.println("查看是否允许带有可变数量的参数:"+constructor.isVarArgs());
System.out.println("该构造方法的入口参数类型依次为:");
Class[] parameterTypes=constructor.getParameterTypes();
//获得所有参数类型
for(int j=0;j<parameterTypes.length;j++){
System.out.println(" "+parameterTypes[j]);
}
System.out.println("该构造方法可能抛出的异常类型为: ");
//获得所有可能抛出的异常信息类型
Class[]exceptionTypes=constructor.getExceptionTypes();
for(int j=0;j<exceptionTypes.length;j++){
System.out.println(" "+exceptionTypes[j]);
}
Example_01 example2=null;
//在主方法最早的循环中,不同的i值对应不同的构造方法
while(example2==null){
try{
//如果该成员变量的访问权限为private,则抛出异常,即不允许访问
if(i==2)//通过执行默认没有参数的构造方法创建对象