反射
利用Java反射机制,可以在程序运行时访问类的所有描述信息(经常需要访问的有 类的构造方法、成员变量和方法),实现逆向控制程序的执行过程
Class类与Java反射
- 通过在Object类中定义的getClass()方法返回一个类型为Class的对象,再用该对象的一些方法,即可访问描述 textField对象的主要描述信息
如:
Class textFieldC = textField.getClass();
- 在通过getFields()和getMethods()方法依次获得权限为public的成员变量和方法时,将包含从超类中继承到的成员变量和方法;而通过方法getDeclareFields()和getDeclaredMethods()只是获得在本类中定义的所有成员变量和方法。
访问构造方法Constructor
- 如果访问指定的构造方法,需要根据该构造方法的入口参数的类型来访问,如:
objectClass.getDeclaredConstructor(String.class,int.class)
- 通过java.lang.reflect.Modifier类可以解析出getModifiers()方法的返回值所表示的修饰符信息,public、protected、private、static、final等
具体方法查看API
访问成员变量Field
每个Field对象代表一个成员变量,利用Field对象可以操纵相应的成员变量。
访问方法Method
如果是访问指定的方法,需要根据该方法的名称和入口参数的类型来访问。如,访问一个名称为print、入口参数类型一次为String和int型的方法:
objectClass.getDeclaredMethod("print",String.class,int.class);
上述三个类具体方法查API
使用Annotation功能
该功能可用于类、构造方法、成员变量、方法、参数等的声明中。该功能并不影响程序的运行,但是会对编译器警告等辅助工具产生影响。
Annotation即注释,看了下代码,是一种和之前一些代码相比比较不同的东西。
定义Annotation类型
定义Annotation类型的关键字为@interface,这个关键字的隐含意思是继承java.lang.annotation.Annotation接口。如:
public @interface NoMemberAnnotation{
}
public @interface OneMemberAnnotation{
String value()
}
- String:成员类型。可用的成员类型有String、Class、primitive、enumerate和annotation以及所列类型的数组。
包含多个成员的Annotation类型:
public @interface MoreMemberAnnotation{
String describe();
Class Type();
}
在为Annotation类型定义成员时,也可以为成员设置默认值。如:
public @interface DefaultValueAnnotation{
String describe() default"<默认值>";
Class type() default void.class;
}
可以通过Annotation类型@Target来设置Annotation类型适用的程序元素种类。枚举类ElementType中的枚举常量用来设置@Target。
枚举常量 | 说明 |
---|---|
ANNOTATION_TYPE | Annotation类型 |
CONSTRUCTOR | 构造方法 |
FIELD | 成员变量和枚举常量 |
LOCAL_VARIABLE | 局部变量 |
METHOD | 方法 |
PACKAGE | 包装 |
PARAMETER | 正式参数 |
TYPE | 类,接口(包括注释类型)或枚举 |
TYPE_PARAMETER | 键入参数 |
TYPE_USE | 使用类型 |
通过Annotation类型@Retention可以设置Annotation的有效范围。枚举类RetentionPolicy中的常量用来设置@Retention,如未设置@Retention,Annotation的有效范围为枚举常量CLASS表示的范围。
枚举常量 | 说明 |
---|---|
SOURCE | 不变异Annotation到类文件中,有效范围最小 |
CLASS | 编译Annotation到类文件中,但是运行时不加载Annotation到JVM中 |
RUNTIME | 运行时加载Annotation到JVM中,有效范围最大 |
例:
import java.lang.annotation.*;
@Target(ElementType.CONSTRUCTOR)
// 用于构造方法
@Retention(RetentionPolicy.RUNTIME)
// 在运行时加载Annotation到JVM中
public @interface Constructor_Annotation {
String value() default "默认构造方法"; // 定义一个具有默认值的String型成员
}
import java.lang.annotation.*;
// 用于字段、方法和参数
@Target( { ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
// 在运行时加载Annotation到JVM中
public @interface Field_Method_Parameter_Annotation {
String describe(); // 定义一个没有默认值的String型成员
Class type() default void.class; // 定义一个具有默认值的Class型成员
}
public class Record {
@Field_Method_Parameter_Annotation(describe = "编号", type = int.class)
// 注释字段
int id;
@Field_Method_Parameter_Annotation(describe = "姓名", type = String.class)
String name;
@Constructor_Annotation()
// 采用默认值注释构造方法
public Record() {
}
@Constructor_Annotation("立即初始化构造方法")
// 注释构造方法
public Record(
@Field_Method_Parameter_Annotation(describe = "编号",
type = int.class) int id,
@Field_Method_Parameter_Annotation(describe = "姓名",
type = String.class) String name) {
this.id = id;
this.name = name;
}
@Field_Method_Parameter_Annotation(describe = "获得编号", type = int.class)
// 注释方法
public int getId() {
return id;
}
@Field_Method_Parameter_Annotation(describe = "设置编号")
// 成员type采用默认值注释方法
public void setId(
// 注释方法的参数
@Field_Method_Parameter_Annotation(describe = "编号",
type = int.class) int id) {
this.id = id;
}
@Field_Method_Parameter_Annotation(describe = "获得姓名",
type = String.class)
public String getName() {
return name;
}
@Field_Method_Parameter_Annotation(describe = "设置姓名")
public void setName(
@Field_Method_Parameter_Annotation(describe = "姓名",
type = String.class) String name) {
this.name = name;
}
}
访问Annotation信息
- 将@Retention设置为RetentionPolicy.RUNTIME,运行程序时通过反射就可以获取到相关的Annotation信息。
- 类Constructor、Field和Method均继承了AccessibleObject类。在AccessibleObject定义了三个关于Annotation的方法。
方法 | 说明 |
---|---|
isAnnotationPresent(Class<? extends Annotation> annotationClass) | 查看是否添加了指定类型的Annotation |
getAnnotation(Class annotationClass) | 获得指定类型的Annotation |
getAnnotations() | 获得所有的Annotation |
在类Constructor和Method中还定义了方法getParameterAnnotations(),用来获得为所有参数添加的Annotation。