通过java的反射机制,程序员可以更深入的控制程序的运行过程。例如,可在程序运行时对象用户输入的信息进行验证,还可以逆向控制程序的执行过程,讲解了反射,另外java还提供了Annotation注解功能,该功能建立在反射机制的基础上,包括定义Annotation类型的方法和程序运行时访问Anntation信息的方法
16.1 反射
反射(Reflection)是指在运行时获取类的信息,并可以动态调用类的方法、访问或修改类的属性,以及构造对象的能力。 Java的反射提供了一套API,允许你在运行时检查类的结构、调用类的方法、获取和设置类的属性,甚至可以实例化对象,而不需要在编译时知道类的具体信息。
反射的一些常见用途包括:
动态加载类:可以在运行时加载未知的类。
在运行时获取类的信息:包括类的名称、父类、接口、方法、字段等。
动态创建对象:可以通过反射在运行时实例化对象,而不需要在编码时知道具体的类。
动态调用方法:可以在运行时调用类的方法,包括私有方法。
动态访问和修改属性:可以在运行时获取和修改类的属性,包括私有属性。
在通过下列一组方法访问构造方法时,将返回 Constructor 类型的对象或数组。每个Constuetor对代表一个构造方法,利用 Constructor 对象可以操纵相应的构造方法;
利用Class类的对象demo1,可以访问用来返回该对象的demo1对象的描述信息,可以访问的主要描述信息如下
组成部分 | 访问方法 | 返回值类型 | 说明 |
包路径 | getPackage() | Package对象 | 获取该类的存放路径 |
类名称 | getName() | String对象 | 获取该类名称 |
继承类 | getSuperclass | Class对象 | 获取该类的继承类 |
实现接口 | getInterfaces() | Class型数组 | 获取该类实现的所有接口 |
构造方法 | getConstructors() | Constructor型数组 | 获取所有权限为public的构造方法 |
getConstructor(Class<?>...parameterTypers) | Constructor对象 | 获取指定构造方法 | |
getDeclaredConstructors() | Constructor型数组 | 获取所有构造方法 | |
getDeclaredConstructors(Class<?>...parameterTypers) | Constructor对象 | 获取自动那个构造方法 | |
方法 | getMethods() | Method型数组 | 获取所有权限为public的指定方法 |
getMethod(String name,Class<?>...parameterTypes) | Method对象 | 获取权限为public的指定方法 | |
getDeclardMethod() | Method型数组 | 获取所有方法 | |
getDeclaredMethod(String name,Class<?>...parameterTypes) | Method对象 | 获取指定方法 | |
成员变量 | getFields() | Field数组 | 获取所有权限为public的成员变量 |
getFields(String name) | Field对象 | 获取权限为public的指定的成员变量 | |
getDeclaredFields() | Field数组 | 获取所有成员变量 | |
getDeclaredField(String name) | Field对象 | 获取指定成员变量 | |
内部类 | getClasses() | Class型数组 | 获取所有权限为public的内部类 |
getDeclaredClasses() | Class型数组 | 获取所有内部类 | |
内部类的声明类 | getDeclaringClass() | Class对象 | 如果改类为内部类,则返回她的成员变量否则返回null |
例题16.1:反射一个类的所有的构造方法
16.1.2 访问成员变量
在Java中,可以使用反射机制来实现对成员变量的访问。通过反射,可以获取类的字段信息,包括字段的名称、类型等,并且可以在运行时修改它们的值,甚至可以访问私有字段。 反射提供了以下方法来访问成员变量:
getField()
getField(String name)
getDeclaredField()
getDeclaredField(String name)
使用反射访问成员变量可以在运行时动态地获取和修改类的状态,但也要小心使用,因为过度使用反射可能会导致代码变得难以维护和理解。
例题16.2:反射一个类的所有成员变量
16.1.3 访问成员方法
访问成员方法是指通过代码动态地调用一个类的方法。在Java中,可以使用反射机制来实现对成员方法的访问。通过反射,可以获取类的方法信息,包括方法的名称、参数类型等,并且可以在运行时调用它们。
反射提供了以下方法来访问成员方法:
getMethod()
getMethod(String name, Class<?>... parameterTypes)
getDeclaredMethod()
getDeclaredMethod(String name, Class<?>... parameterTypes)
例题16.3:反射一个类的所有成员方法
16.2 Annotation注解功能
在定义Annotation 类型时,也需要用到用来定义接口的 interface 关键字,但需要在 interface 关键字前加一个“@”符号,即定义 Annotation 类型的关键字为@interface,这个关键字的隐含意思是继承了java.lang.annotation.Annotation 接口。例如,下面的代码就定义了一个 Annotation类型:
public @interface NoMemberAnnotation {
}
上面定义的Annotation类型@NoMemberAnnotation 未包含任何成员,这样的Annotation类型被称为marker annotation。下面的代码定义了一个只包含一个成员的Annotation类型:
public @interface OneMemberAnnotation {
String value();
}
String: 成员类型。可用的成员类型有 String、Class、primitive、 enumerated和annotation以及所列类型的数组。
value:成员名称。如果在所定义的 Annotation 类型中只包含一个成员,通常将成员名称命名为 value。
下面的代码定义了一个包含多个成员的 Annotation 类型:
public @interface MoreMemberAnnotation {
String describe();
Class type();
}
在为Annotation 类型定义成员时,也可以为成员设置默认值。例如,下面的代码在定义Amnotation类型时就为成员设置了默认值:
public @interface DefaultValueAnnotation {
String describe() default "<默认值>";
Class type() default void.class;
}
内置注解
@Override 限定重写父类方法 作用范围成员方法
@SuppressWarnings 抑制编译器警告 作用范围类、成员属性、成员方法
@Deprecated 标示已过时 作用范围类、成员属性、成员方法
例题16.4:创建自定义的注释