通过Java的反射机制,可以在程序中访问已经装载到JVM中的Java对象的描述,实现访问、检测、修改描述Java对象本身信息的功能。java.lang.reflect包提供了反射的支持。
1.获取对象的类的对象:Class 类对象名 = 对象.getClass()
Class 类对象名 = 对象.getClass()
类对象通过反射可以访问的主要描述信息:
通过反射可访问的主要描述信息
组成部分 | 访问方法 | 返回值类型 | 说明 |
访问包路径 | getPackage() | Package对象 | 获得该类的存放路径 |
访问类名称 | getName() | String对象 | 获得该类的名称 |
访问继承类 | getSuperclass() | Class对象 | 获得该类继承的类 |
访问实现接口 | getInterfaces() | Class型数组 | 获得该类实现的所有接口 |
访问构造方法 | getConstructors() | Constructor型数组 | 获得所有权限为public的构造方法 |
getConstructors(Class<?>...parameterTypes) | Constructor对象 | 获得指定的权限为public的构造方法 | |
getDeclaredConstructors() | Constructor型数组 | 获得所有构造方法,按照声明顺序返回 | |
getDeclaredConstructors(Class<?>...parameterTypes) | Constructor对象 | 获取指定构造方法 | |
访问方法 | getMethods() | Method型数组 | 获取所有权限为public的方法 |
getMethod(String name, Class<?>...parameterTypes) | Method对象 | 获得指定的权限为public的方法 | |
getDeclaredMethods() | Method型数组 | 获得所有的方法,按声明顺序返回 | |
getDeclaredMethod(String name, Class<?>...parameterTypes) | Method对象 | 获得指定的方法 | |
访问成员变量 | getFields() | Field型数组 | 获得所有权限为public的成员变量 |
getField(String name) | Field对象 | 获得指定的权限为public的成员变量 | |
getDeclaredFields() | Field型数组 | 获得所有的成员变量,按声明顺序返回 | |
getDeclaredField(String name) | Field对象 | 获得指定的成员变量 | |
访问内部类 | getClasses() | Class型数组 | 获得所有权限为public的内部类 |
getDeclaredClasses() | Class型数组 | 获得所有内部类 | |
访问内部类的声明类 | getDeclaringClass() | Class对象 | 如果该类为内部类,则返回他的成员类,否则返回null |
Tips:
getFields()和getMethods()方法获取的成员变量和方法,包括从超类中继承到的成员变量和方法。而getDeclaredFields()方法和getDeclaredMethods()方法,只会获取本类中定义的所有成员变量和方法。
2.访问构造方法
2.1 getConstructors()
2.2 getConstructor(Class<?>...parameterTypes)
2.3 getDeclaredConstructors()
2.4 getDeclaredConstructor(Class<?>...parameterTypes)
如果访问指定的构造方法,需要根据构造方法的参数类型来访问,如
objectClass.getDeclaredConstructor(String.class, int.class);
objectClass.getDeclaredConstructor(new Class[]{String.class, int.class})
Constructor类常用方法
方法 | 返回值类型 | 说明 |
isVarArgs() | boolean | 判断该构造方法是否允许带可变数量的参数,如果允许,返回true,反之返回false |
getParameterTypes() | Class型数组 | 获得该构造方法的各个参数类型 |
getExceptionTypes() | Class型数组 | 获得该构造方法可能抛出的异常类型 |
newInstance(Object...initargs) | 类的对象 | 通过该构造方法利用指定参数创建一个该类的对象,如果未设置参数,则采用默认的无参数构造方法 |
setAccessible(boolean flag) | void | 如果该构造方法为private修饰,则不允许通过反射利用newInstance(Object...initargs)方法创建对象。如果先执行了此方法,并将入口参数设为true,则允许创建 |
getModifiers() | int | 获得该构造方法所采用修饰符的个数 |
Tips:
通过.java.lang.reflect.Modifier类可以解析出getModifiers()方法的返回值所表示的修饰符信息;在该类中提供了以下列的静态方法,既可以查看是否被指定的修饰符修饰,也可以以字符串的形式获得所有修饰符。
Modifier类中的常用解析方法
静态方法 | 说明 |
isPublic(int mod) | 查看是否被public修饰 |
isProtected(int mod) | 查看是否被protected修饰 |
isPrivate(int mod) | 查看是否被private修饰 |
isStatic(int mod) | 查看是否被static修饰 |
isFinal(int mod) | 查看是否被final修饰 |
toString(int mod) | 以字符串的形式返回所有修饰符 |
Tips:
参数(int mod)中的mod,即Constructor类中的getModifiers()方法的返回值。
int mod = constructor.getModifiers();
boolean isEmbellishByPrivate = Modifier.isPrivate(mod);
String embellishment = Modifier.toString(mod);
Example_o1.java:
package reflectdemo;
public class Example_01 {
String s;
int i, i2, i3;
private Example_01() {
}
protected Example_01(String s, int i) {
this.s = s;
this.i = i;
}
public Example_01(String... strings) {
if (strings.length > 0) {
i = Integer.valueOf(strings[0]);
}
if (strings.length > 1) {
i2 = Integer.valueOf(strings[1]);
}
if (strings.length > 2) {
i3 = Integer.valueOf(strings[2]);
}
}
public void print() {
System.out.println("s=" + s);
System.out.println("i=" + i);
System.out.println("i2=" + i2);
System.out.println("i3=" + i3);
}
}
Main_01.java:
package reflectdemo;
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 exampleC = example.getClass();
//获取所有构造方法
Constructor[] declaredConstructors = exampleC.getDeclaredConstructors();
for (int x = 0; x < declaredConstructors.length; x++) {
Constructor constructor = declaredConstructors[x];
boolean is_vars_args = constructor.isVarArgs(); //判断此构造方法是否允许带有可变数量参数
System.out.println("构造方法是:" + constructor);
System.out.println("查看是否允许带有可变数量参数:" + is_vars_args);
System.out.println("该构造方法的入口参数类型依次是:");
Class[] parameterTypes = constructor.getParameterTypes(); //获取该构造方法的各个参数类型
for (int j = 0; j < parameterTypes.length; j++) {
System.out.println(" " + parameterTypes[j]);
}
Class[] exceptionTypes = constructor.getExceptionTypes(); //获取所有该构造方法可能抛出的异常
for (int k = 0; k < exceptionTypes.length; k++) {
System.out.println("该构造方法可能抛出的异常类型有:" + exceptionTypes[k]);
}
Example_01 example2 = null;
while (example2 == null) {
try {
if (x == 2) //此处访问无参数的构造方法
example2 = (Example_01) constructor.newInstance();
else if (x == 1) //此处访问参数为字符串和整型的构造方法
example2 = (Example_01) constructor.newInstance("7", 5);
else { //此处访问参数为数组的构造方法
Object[] parameters = new Object[]{new String[]{"100", "200", "300"}};
example2 = (Example_01) constructor.newInstance(parameters);
}
} catch (Exception e) {
System.out.println("在创建对象时抛出异常,下面执行setAccessible()方法:");
constructor.setAccessible(true);
}
}
if (example2 != null) {
example2.print();
System.out.println();
}
}
}
}
输出:
构造方法是:public reflectdemo.Example_01(java.lang.String[])
查看是否允许带有可变数量参数:true
该构造方法的入口参数类型依次是:
class [Ljava.lang.String;
s=null
i=100
i2=200
i3=300
构造方法是:protected reflectdemo.Example_01(java.lang.String,int)
查看是否允许带有可变数量参数:false
该构造方法的入口参数类型依次是:
class java.lang.String
int
s=7
i=5
i2=0
i3=0
构造方法是:private reflectdemo.Example_01()
查看是否允许带有可变数量参数:false
该构造方法的入口参数类型依次是:
在创建对象时抛出异常,下面执行setAccessible()方法:
s=null
i=0
i2=0
i3=0
3.访问成员变量
通过以下方法访问成员变量时,将返回Field类型的对象或数组;每个Field对象代表一个成员变量,利用这些Field对象可以操作相应的成员变量。
3.1 getFields()
3.2 getField(String name)
3.3 getDeclaredFields()
3.4 getDeclaredField(String name)
访问指定的成员变量birthday:
Example_01 example = new Example_01("10", "20", "30"); Class exampleC = example.getClass(); //获取所有构造方法 Field birthdy_field = exampleC.getDeclaredField("birthday");
Field类中提供的常用方法
Field类的常用方法
方法 | 返回值类型 | 说明 |
getName() | String | 获取该成员变量的名称 |
getType() | Class对象 | 获取该成员变量的类型 |
get(Object obj) | Object型 | 获取指定对象Object中成员变量的值 |
set(Object obj, Object value) | void | 将指定对象obj中的成员变量的值设置为value |
getInt(Object obj) | int | 获得指定对象obj中类型为int的成员变量的值 |
setInt(Object obj, int value) | void | 将指定对象obj中类型为int的成员变量的值设置为value |
getFloat(Object obj) | float | 获得指定对象obj中类型为float的成员变量的值 |
setFloat(Object obj,float value) | void | 将指定对象obj中类型为float的成员变量的值设置为value |
getBoolean(Object obj) | boolean | 获得指定对象obj中类型为boolean的成员变量的值 |
setBoolean(Object obj, boolean value) | void | 将指定对象obj中类型为boolean的成员变量的值设置为value |
setAccessible(boolean flag) | void | 此方法可以设置是否忽略权限限制直接访问private等私有权限的成员变量 |
getModifers() | int | 获得该成员变量被解析出的修饰符的整数 |
Example_02.java:
package reflectdemo;
public class Example_02 {
int i;
public float f;
protected boolean b;
private String s;
}
Main_02.java:
package reflectdemo;
import java.lang.reflect.Field;
public class Main_02 {
public static void main(String[] args) {
Example_02 example = new Example_02();
Class exampleC = example.getClass();
//获得所有成员变量
Field[] declaredFields = exampleC.getDeclaredFields();
for (int a = 0; a < declaredFields.length; a++) { //遍历成员变量
Field field = declaredFields[a];
System.out.println("名称为:" + field.getName()); //获得成员变量名称
Class fieldType = field.getType(); //获得成员变量类型
System.out.println("类型为:" + fieldType);
boolean isTurn = true;
while (isTurn) {
try {
isTurn = false;
//如果该成员变量的访问权限为private,则抛出异常,不允许访问
System.out.println("修改前的值为:" + field.get(example));
if (fieldType.equals(int.class)) {
System.out.print("利用方法setInt()修改成员变量的值:");
field.setInt(example, 165); //为int型成员变量赋值
} else if (fieldType.equals(float.class)) {
System.out.print("利用setFloat()方法修改成员变量:");
field.setFloat(example, 99.90f);
} else if (fieldType.equals(boolean.class)) {
System.out.print("利用setBoolean()方法修改成员变量:");
field.setBoolean(example, true);
} else {
System.out.print("利用set()方法修改成员变量的值:");
field.set(example, "春田");
}
//获取修改后的成员变量的值
System.out.println(field.get(example));
} catch (Exception e) {
System.out.println("设置成员变量时抛出异常," + "下面执行setAccessible()方法!");
field.setAccessible(true); //设置为允许访问
isTurn = true;
}
}
System.out.println("----------");
}
}
}
输出:
名称为:i
类型为:int
修改前的值为:0
利用方法setInt()修改成员变量的值:165
----------
名称为:f
类型为:float
修改前的值为:0.0
利用setFloat()方法修改成员变量:99.9
----------
名称为:b
类型为:boolean
修改前的值为:false
利用setBoolean()方法修改成员变量:true
----------
名称为:s
类型为:class java.lang.String
设置成员变量时抛出异常,下面执行setAccessible()方法!
修改前的值为:null
利用set()方法修改成员变量的值:春田
----------
4.访问方法
利用下面的方法访问方法时,将返回Method类型的对象或数组。每个Method对象代表一个方法,利用Method对象可以操作相应的方法。
4.1 getMethods()
4.2 getMethod(String name, Class<?>...parameterTypes)
4.3 getDeclaredMethods()
4.4 getDeclaredMethod(String name, Class<?>...parameterTypes)
如果访问指定的方法,需要根据该方法的名称和入口参数类型来访问。
1. objectClass.getDeclaredMethod("print", String.class, int.class)
2. objectClass.getDeclaredMethod("print", new Class[] {String.class, int.class})
Example_02 example = new Example_02(); Class exampleC = example.getClass(); //获得所有成员方法 Method[] declaredFields = exampleC.getDeclaredMethods();
Method类的常用方法
方法 | 返回值类型 | 说明 |
getName() | String | 获取方法名称 |
getParamterTypes() | Class型数组 | 按照声明顺序获取方法各个参数类型 |
getReturnType() | Class型数组 | 获取该方法的返回值类型 |
getExceptionType() | Class型数组 | 获取该方法可能抛出的异常类型 |
invoke(Object obj, Object...args) | Object型 | 利用指定参数args执行指定对象中的该方法 |
isVarArgs() | boolean | 判断该方法是否允许使用可变数量的参数,允许返回true,反之返回false |
setAccessible(boolean flag) | void | 此方法可以设置是否忽略权限限制直接访问private等私有权限的成员变量 |
getModifiers() | int | 获得该成员变量被解析出的修饰符的整数 |
Example_03.java:
package reflectdemo;
public class Example_03 {
static void staticMethod() {
System.out.println("执行staticMethod()方法");
}
public int publicMethod(int i) {
System.out.println("执行publicMethod()方法");
return i * 100;
}
protected int protectedMethod(String s, int i) throws NumberFormatException {
System.out.println("执行protectedMethod()方法");
return Integer.valueOf(s) + i;
}
private String privateMethod(String... strings) {
System.out.println("执行privateMethod()方法");
StringBuffer stringBuffer = new StringBuffer(); //StringBuffer线程安全,StringBuilder线程不安全
for (int i = 0; i < strings.length; i++) {
stringBuffer.append(strings[i]);
}
return stringBuffer.toString();
}
}
Main_03.java:
package reflectdemo;
import java.lang.reflect.Method;
public class Main_03 {
public static void main(String[] args) {
Example_03 example = new Example_03();
Class exampleC = example.getClass();
Method[] declaredMethods = exampleC.getDeclaredMethods();
for (int m = 0; m < declaredMethods.length; m++) {
Method method = declaredMethods[m];
System.out.println("名称为:" + method.getName()); //获得方法名称
System.out.println("是否允许带有可变数量的参数:" + method.isVarArgs());
System.out.println("入口参数类型依次为:");
Class[] parameterTypes = method.getParameterTypes(); //获得所有参数类型
for (int c = 0; c < parameterTypes.length; c++) {
System.out.println(parameterTypes[c]);
}
System.out.println("获得方法的返回值类型是:" + method.getReturnType()); //获取方法的返回值类型
System.out.println("方法可能抛出的异常有:");
Class[] exceptionTypes = method.getExceptionTypes(); //获取方法可能抛出的异常类型
for (int e = 0; e < exceptionTypes.length; e++) {
System.out.println(" " + exceptionTypes[e]);
}
boolean isTurn = true;
while (isTurn) {
isTurn = false;
//如果该方法的访问权限为private,则抛出异常,即不允许访问,需要setAccessible()方法修改权限
try {
if (method.getName().equals("staticMethod")) {
method.invoke(example); //执行没有入口参数的方法
} else if ("publicMethod".equals(method.getName())) {
System.out.println(method.invoke(example, 165)); //执行有1个int型参数的方法
} else if (method.getName().equals("protectedMethod")) {
System.out.println(method.invoke(example, "7", 5)); //执行1个String型参数和1个int型参数的方法
} else {
Object[] parameters = new Object[][]{new String[]{"M", "W", "Q"}};
String returnValues = (String) method.invoke(example, parameters);
System.out.println("返回值是:" + returnValues);
}
} catch (Exception e) {
System.out.println("执行setAccessible()方法!");
method.setAccessible(true);
isTurn = true;
}
}
System.out.println("----------");
}
}
}
输出:
名称为:staticMethod
是否允许带有可变数量的参数:false
入口参数类型依次为:
获得方法的返回值类型是:void
方法可能抛出的异常有:
执行staticMethod()方法
----------
名称为:publicMethod
是否允许带有可变数量的参数:false
入口参数类型依次为:
int
获得方法的返回值类型是:int
方法可能抛出的异常有:
执行publicMethod()方法
16500
----------
名称为:protectedMethod
是否允许带有可变数量的参数:false
入口参数类型依次为:
class java.lang.String
int
获得方法的返回值类型是:int
方法可能抛出的异常有:
class java.lang.NumberFormatException
执行protectedMethod()方法
12
----------
名称为:privateMethod
是否允许带有可变数量的参数:true
入口参数类型依次为:
class [Ljava.lang.String;
获得方法的返回值类型是:class java.lang.String
方法可能抛出的异常有:
执行setAccessible()方法!
执行privateMethod()方法
返回值是:MWQ
----------
5.使用Annotation注解功能
Java中Annotation注解功能,可用于类、构造方法、成员变量、方法、参数等的声明中,该功能不影响程序的运行,但是会对编译器警告等辅助工具产生影响。
5.1 定义Annotation类型:@interface
@interface关键字隐含的意思就是继承java.lang.annotation.Annotation接口。
5.1.1 无任何成员marker annotation
public @interface noMemberAnnotation{
//无任何成员
}
5.1.2 有成员annotation
public @interface OneMemberAnnotation{
String value();
}
String:成员类型。可用的成员类型有:String ,Class,primitive,enumerated,annotation,以及这些所列类型的数组。
value:成员名称。如果所定义的Annotation注解中只有一个成员,通常这个成员被命名为value.
5.1.3 成员有默认值的annotation
public @interface DefaultValueAnnotation{
String describe() default "默认值";
Class type() default void.class;
}
5.2 @Target设置Annotation类型适用的程序元素种类
如果我们的注解未设置@Target,则表示这个注解适用于所有程序元素。@Target的值通常是枚举类ElementType中的枚举常量。
枚举类ElementType中的枚举常量
枚举常量 | 说明 |
ElementType.ANNOTATION_TYPE | 表示用于Annotation类型 |
ElementType.TYPE | 表示用于类、接口、枚举、Annotation类型 |
ElementType.CONSTRUCTOR | 表示用于构造方法 |
ElementType.FIELD | 表示用于成员变量和枚举常量 |
ElementType.METHOD | 表示用于方法 |
ElementType.PARAMETER | 表示用于参数 |
ElementType.LOCAL_VARIABLE | 表示用于局部变量 |
ElementType.PACKAGE | 表示用于包 |
5.3 @Retention设置Annotation类型的有效范围
通过@Retention可以设置我们Annotation注解的有效范围。如果我们的注解未设置@Retention,则这个注解的有效范围为枚举常量CLASS表示的范围。通常我们使用枚举类RetentionPolicy中的枚举常量来设置@Retention的值。
枚举类RetentionPolicy中的枚举常量
枚举常量 | 说明 |
RetentionPolicy.SOURCE | 表示不编译Annotaion注解到类文件中,范围最小 |
RetentionPolicy.CLASS | 表示编译Annotation注解到类文件中,但是在运行时不加载Annotation到JVM中 |
RetentionPolicy.RUNTIME | 表示在运行时加载Annotation到JVM中,有效范围最大 |
5.4 访问Annotation信息
只要在定义Annotation注解类时将@Retention设置为RetentionPolicy.RUNTIMT,那么在运行程序时就可以通过反射获取到相关的Annotation注解信息,如获得构造方、字段、方法的Annotation信息。
5.4.1 isAnnotationPresent(Class<? extends Annotation> annotationClass)方法
查看对象是否添加了指定的annotation注解,返回boolean值。
5.4.2 getAnnotation(Class<T> annotionClass)方法
获取对象指定的annotation注解,如果有,返回对应的对象,否则返回null。
5.4.3 getAnnotations()方法
获取对象所有的annotation注解,返回一个Annotation类型的数组。
5.4.4 getParameterAnnotation()方法
获取构造方法Constructor类和方法Method类中注解的特用方法,用来获得方法的参数添加的注解,以Annotation类型的数组返回,数组中的顺序与声明的顺序相同。
如果该方法没有参数,则返回一个长度为0的数组;如果存在未添加Annotation注解的参数,则用一个长度为0的嵌套数组占位。
Constructor_Annotation.java:
/**
* 定义一个注释构造方法的注解
**/
package reflectdemo;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME) //指定运行时加载到JVM中
@Target(ElementType.CONSTRUCTOR) //指定适用元素为构造方法
public @interface Constructor_Annotation {
String value() default "默认构造方法"; //定义一个具有默认值的String类型成员value
}
Field_Method_Parameter_Annotation.java:
/**
* 定义一个适用于字段、方法、参数的注解
*/
package reflectdemo;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME) //运行时加载到jvm
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) //适用于Field,Method,Parameter
public @interface Field_Method_Parameter_Annotation {
String describe(); //没有默认值的String成员describe
Class type() default void.class; //有默认值的Class类型成员type
}
Record.java:
package reflectdemo;
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 = "设置编号的方法")
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;
}
}
反射获取构造方法的注解:
readAnnoInfo.java:
package reflectdemo;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
public class readAnnoInfo {
public static void main(String[] args) {
Record record = new Record();
Class recordC = record.getClass();
Constructor[] declaredConstructor = recordC.getDeclaredConstructors(); //获取所有构造方法
//查看构造方法是否具有指定类型的注释
System.out.println("--------构造方法的描述如下----------");
for (int c = 0; c < declaredConstructor.length; c++) {
Constructor constructor = declaredConstructor[c];
if (constructor.isAnnotationPresent(Constructor_Annotation.class)) {
//获取指定的Annotation注解
Constructor_Annotation ca = (Constructor_Annotation) constructor.getAnnotation(Constructor_Annotation.class);
System.out.println("构造方法的注解是:" + ca.value()); //获取注释信息
}
}
}
}
输出:
--------构造方法的描述如下----------
构造方法的注解是:默认构造方法
构造方法的注解是:有立即初始化参数的构造方法~
反射获取构造方法的参数的注释:
readAnnoInfo.java:
package reflectdemo;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
public class readAnnoInfo {
public static void main(String[] args) {
Record record = new Record();
Class recordC = record.getClass();
Constructor[] declaredConstructor = recordC.getDeclaredConstructors(); //获取所有构造方法
//查看构造方法是否具有指定类型的注释
for (int c = 0; c < declaredConstructor.length; c++) {
Constructor constructor = declaredConstructor[c];
//获取构造方法的参数的注释
Annotation[][] param_annotations = constructor.getParameterAnnotations();
System.out.println("--------方法的参数描述如下----------");
for (int p = 0; p < param_annotations.length; p++) {
int length = param_annotations[p].length;
if (length == 0) {
System.out.println("参数未添加注释~");
} else
for (int j = 0; j < param_annotations[p].length; j++) {
//获得参数的注解
Field_Method_Parameter_Annotation param_inno = (Field_Method_Parameter_Annotation) param_annotations[p][j];
System.out.print(" "+ param_inno.describe()); //获得参数的描述
System.out.println(" "+ param_inno.type()); //获取参数的类型
}
}
}
}
}
输出:
--------方法的参数描述如下----------
编号 int
姓名 class java.lang.String
反射获取字段的注释:
readAnnoInfo.java:
package reflectdemo;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
public class readAnnoInfo {
public static void main(String[] args) {
Record record = new Record();
Class recordC = record.getClass();
//获取字段的注释信息
Field[] myDeclaredFields = recordC.getDeclaredFields();
System.out.println("--------字段描述如下----------");
for (int f = 0; f < myDeclaredFields.length; f++) {
Field myField = myDeclaredFields[f];
//判断是否有指定的注释类型
if (myField.isAnnotationPresent(Field_Method_Parameter_Annotation.class)) {
//获得指定类型的注释
Field_Method_Parameter_Annotation fa = myField.getAnnotation(Field_Method_Parameter_Annotation.class);
System.out.print(" " + fa.describe());
System.out.println(" " + fa.type());
}
}
}
}
输出:
--------字段描述如下----------
编号 int
姓名 class java.lang.String
反射获取参方法的注解+方法包含参数的注解
readAnnoInfo.java:
package reflectdemo;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class readAnnoInfo {
public static void main(String[] args) {
Record record = new Record();
Class recordC = record.getClass();
//获取方法及其参数的注释信息
Method[] myMethods = recordC.getDeclaredMethods();
System.out.println("--------自定义方法注解描述如下----------");
for (int m = 0; m < myMethods.length; m++) {
Method method = myMethods[m];
if (method.isAnnotationPresent(Field_Method_Parameter_Annotation.class)) {
Field_Method_Parameter_Annotation method_anno = method.getAnnotation(Field_Method_Parameter_Annotation.class);
System.out.print(" " + method_anno.describe()); //获取方法的描述
System.out.println(" " + method_anno.type()); //获取方法的类型
//获取该方法的参数的注释
Annotation[][] param_annotations = method.getParameterAnnotations();
System.out.println("=======自定义方法的参数注解描述如下=======");
for (int p = 0; p < param_annotations.length; p++) {
int length = param_annotations[p].length;
if (length == 0) {
System.out.println("自定义方法的参数没有添加Annotation注释信息");
} else
for (int j = 0; j < length; j++) {
//获取指定类型注释
Field_Method_Parameter_Annotation param_anno = (Field_Method_Parameter_Annotation) param_annotations[p][j];
System.out.print(" " + param_anno.describe());
System.out.println(" " + param_anno.type());
}
}
}
System.out.println();
}
}
}
输出:
--------自定义方法注解描述如下----------
获得姓名的方法 class java.lang.String
=======自定义方法的参数注解描述如下=======
设置姓名的方法 void
=======自定义方法的参数注解描述如下=======
姓名 class java.lang.String
获得编号的方法 int
=======自定义方法的参数注解描述如下=======
设置编号的方法 void
=======自定义方法的参数注解描述如下=======
编号 int
反射readAnnoInfo.java文件整体:
package reflectdemo;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class readAnnoInfo {
public static void main(String[] args) {
Record record = new Record();
Class recordC = record.getClass();
Constructor[] declaredConstructor = recordC.getDeclaredConstructors(); //获取所有构造方法
// 查看构造方法是否具有指定类型的注释
System.out.println("--------构造方法的描述如下----------");
for (int c = 0; c < declaredConstructor.length; c++) {
Constructor constructor = declaredConstructor[c];
if (constructor.isAnnotationPresent(Constructor_Annotation.class)) {
//获取指定的Annotation注解
Constructor_Annotation ca = (Constructor_Annotation) constructor.getAnnotation(Constructor_Annotation.class);
System.out.println("构造方法的注解是:" + ca.value()); //获取注释信息
}
//获取构造方法的参数的注释
Annotation[][] param_annotations = constructor.getParameterAnnotations();
System.out.println("--------方法的参数描述如下----------");
for (int p = 0; p < param_annotations.length; p++) {
int length = param_annotations[p].length;
if (length == 0) {
System.out.println("参数未添加注释~");
} else
for (int j = 0; j < param_annotations[p].length; j++) {
//获得参数的注解
Field_Method_Parameter_Annotation param_inno = (Field_Method_Parameter_Annotation) param_annotations[p][j];
System.out.print(" " + param_inno.describe()); //获得参数的描述
System.out.println(" " + param_inno.type()); //获取参数的类型
}
}
}
//获取字段的注释信息
Field[] myDeclaredFields = recordC.getDeclaredFields();
System.out.println("--------字段描述如下----------");
for (int f = 0; f < myDeclaredFields.length; f++) {
Field myField = myDeclaredFields[f];
//判断是否有指定的注释类型
if (myField.isAnnotationPresent(Field_Method_Parameter_Annotation.class)) {
//获得指定类型的注释
Field_Method_Parameter_Annotation fa = myField.getAnnotation(Field_Method_Parameter_Annotation.class);
System.out.print(" " + fa.describe());
System.out.println(" " + fa.type());
}
}
//获取方法及其参数的注释信息
Method[] myMethods = recordC.getDeclaredMethods();
System.out.println("--------自定义方法注解描述如下----------");
for (int m = 0; m < myMethods.length; m++) {
Method method = myMethods[m];
if (method.isAnnotationPresent(Field_Method_Parameter_Annotation.class)) {
Field_Method_Parameter_Annotation method_anno = method.getAnnotation(Field_Method_Parameter_Annotation.class);
System.out.print(" " + method_anno.describe()); //获取方法的描述
System.out.println(" " + method_anno.type()); //获取方法的类型
//获取该方法的参数的注释
Annotation[][] param_annotations = method.getParameterAnnotations();
System.out.println("=======自定义方法的参数注解描述如下=======");
for (int p = 0; p < param_annotations.length; p++) {
int length = param_annotations[p].length;
if (length == 0) {
System.out.println("自定义方法的参数没有添加Annotation注释信息");
} else
for (int j = 0; j < length; j++) {
//获取指定类型注释
Field_Method_Parameter_Annotation param_anno = (Field_Method_Parameter_Annotation) param_annotations[p][j];
System.out.print(" " + param_anno.describe());
System.out.println(" " + param_anno.type());
}
}
}
System.out.println();
}
}
}
输出:
--------构造方法的描述如下----------
构造方法的注解是:默认构造方法
--------方法的参数描述如下----------
构造方法的注解是:有立即初始化参数的构造方法~
--------方法的参数描述如下----------
编号 int
姓名 class java.lang.String
--------字段描述如下----------
编号 int
姓名 class java.lang.String
--------自定义方法注解描述如下----------
获得姓名的方法 class java.lang.String
=======自定义方法的参数注解描述如下=======
设置姓名的方法 void
=======自定义方法的参数注解描述如下=======
姓名 class java.lang.String
获得编号的方法 int
=======自定义方法的参数注解描述如下=======
设置编号的方法 void
=======自定义方法的参数注解描述如下=======
编号 int