导图社区 Java反射
通过Java反射机制,可以在程序中访问已经装载到JVM中的Java对象的描述,实现访问、检测和修改描述Java对象本身信息的功能。Java反射机制的功能非常强大,在java.lang.reflect包中提供了对该功能的支持。 众所周知,所有Java类均继承了Object类,在Object类中定义了一个getClass()方法,该方法返回一个类型为Class的对象。
编辑于2023-01-13 14:05:30 贵州微信小程序开发知识整理,系统地介绍了微信小程序开发的基础知识,帮助开发者更好地理解和掌握小程序开发的要点和流程。
SpringFramework技术的介绍,SpringFramework,通常简称为Spring,是一个开源的企业级Java应用程序框架,由Rod Johnson创建,并于2004年首次发布。Spring Framework的主要目标是简化企业级Java开发,提高开发效率和应用程序的可维护性。
Maven的特性以及使用部署方法,Maven介绍:Maven是一款为Java项目构建管理、依赖管理的工具(软件),使用Maven可以自动化构建、测试、打包和发布项目,大大提高了开发效率和质量。
社区模板帮助中心,点此进入>>
微信小程序开发知识整理,系统地介绍了微信小程序开发的基础知识,帮助开发者更好地理解和掌握小程序开发的要点和流程。
SpringFramework技术的介绍,SpringFramework,通常简称为Spring,是一个开源的企业级Java应用程序框架,由Rod Johnson创建,并于2004年首次发布。Spring Framework的主要目标是简化企业级Java开发,提高开发效率和应用程序的可维护性。
Maven的特性以及使用部署方法,Maven介绍:Maven是一款为Java项目构建管理、依赖管理的工具(软件),使用Maven可以自动化构建、测试、打包和发布项目,大大提高了开发效率和质量。
反射
通过Java的反射机制,程序员可以更深入地控制程序的运行过程。例如,可在程序运行时对用户输入的信息进行验证,还可以逆向控制程序的执行过程。 另外,Java还提供了Annotation功能,该功能建立在反射机制的基础上。本节对此也作了讲解,包括定义Annotation类型的方法和在程序运行时访问Annotation信息的方法。
一、 Class类与Java反射
I. 通过Java反射机制,可以在程序中访问已经装载到JVM中的Java对象的描述,实现访问、检测和修改描述Java对象本身信息的功能。Java反射机制的功能非常强大,在java.lang.reflect包中提供了对该功能的支持。 众所周知,所有Java类均继承了Object类,在Object类中定义了一个getClass()方法,该方法返回一个类型为Class的对象。例如下面的代码: Class textFieldC = textField.getClass(); //textField为JTextField类的对象 利用Class类的对象textFieldC,可以访问用来返回该对象的textField对象的描述信息。可以访问的主要描述信息如表所示
在通过getFields()和getMethods()方法依次获得权限为public的成员变量和方法时,将包含从超类中继承到的成员变量和方法;而通过方法getDeclaredFields()和getDeclaredMethods()只是获得在本类中定义的所有成员变量和方法。
II. 访问构造方法:在通过下列一组方法访问构造方法时,将返回Constructor类型的对象或数组。每个Constructor对象代表一个构造方法,利用Constructor对象可以操纵相应的构造方法
1||| getConstructors()
2||| getConstructor(Class<?>…parameterTypes)
3||| getDeclaredConstructors()
4||| getDeclaredConstructor(Class<?>…perameterTypes)
如果是访问指定的构造方法,需要根据该构造方法的入口参数的类型来访问。例如,访问一个入口参数类型依次为String和int型的构造方法,通过下面两种方式均可实现。 objectClass.getDeclaredConstructor(String.class,int.class); objectClass.getDeclaredConstructor(new Class[ ](String.class,int.class));
Constructor类常用方法
1||| isVarArgs():查看该构造方法是否允许带有可变数量的参数,如果允许则返回true,否则返回false
2||| getParameterTypes():按照声明顺序以Class数组的形式获得该构造方法的各个参数的类型
3||| getExceptionTypes():以Class数组的形式获得该构造方法可能抛出的异常类型
4||| newInstance(Object...initargs):通过该构造方法利用指定参数创建一个该类的对象,如果未设置参数则表示采用默认无参的构造方法
5||| setAccessible(boolean flag):如果该构造方法的权限为private,默认为不允许通过反射利用newInstance(Object...initargs)方法创建对象,如果先执行该方法,并将入口参数设为true,则允许创建
6||| getModifiers():获得可以解析出该构造方法所采用修饰符的整数
通过java.lang.reflect.Modifier类可以解析出getModifiers()方法的返回值所表示的修饰符信息,在该类中提供了一系列用来解析的静态方法,既可以查看是否被指定的修饰符修饰,还可以以字符串的形式获得所有修饰符。该类常用静态方法如下所示
1||| isPublic(int mod):查看是否被public修饰,如果是则返回true,否则返回false
2||| isProtected(int mod):查看是否被protected修饰符修饰,如果是则返回true,否则返回false
3||| isPrivate(int mod):查看是否被private修饰符修饰,如果是则返回true,否则返回false
4||| isStatic(int mod):查看是否被static修饰符修饰,如果是返回true,否则返回false
5||| isFinal(int mod):查看是否被final修饰符修饰,如果是则返回true,否则返回false
6||| toString(int mod):以字符串的形式返回所有修饰符
例如要判断对象constructor所代表的构造方法是否被private修饰,以及以字符串形式获得该构造方法的所有修饰符的典型代码如下: int modifiers=constructor.getModifiers(); boolean isEmbellishByPrivate=Modifier.isPrivate(modifiers); String embellishment=Modifier.toString(modifiers);
实例代码: package com.REFLECT; 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(); //获取类 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; while (example2==null) { try{ //如果该成员变量的访问权限为private,则抛出异常,即不允许访问 if(i==2) { example2 = (Example_01) constructor.newInstance(); //通过执行默认没有参数的构造方法创建对象 } else { //通过执行具有两个参数的构造方法创建对象 if (i == 1) { example2 = (Example_01) constructor.newInstance("4", 7); } else { //通过执行可变数量参数的构造方法创建对象 Object[] parameter = new Object[]{new String[]{"100", "200", "300"}}; example2 = (Example_01) constructor.newInstance(parameter); } } }catch(Exception e) { System.out.println("在创建对象时抛出异常,下面执行setAccessible()方法"); constructor.setAccessible(true); //设置为允许访问 } } if(example2!=null) { example2.print(); System.out.println(); } } } }
package com.REFLECT; public class Example_01 { String s; int i1,i2,i3; private Example_01() { System.out.println("该构造方法使用private修饰"); } protected Example_01(String s,int i) { this.s=s; this.i1=i; } public Example_01(String...strings)throws NumberFormatException { if(0<strings.length) i1=Integer.valueOf(strings[0]); if(1<strings.length) i2=Integer.valueOf(strings[1]); if(2<strings.length) i3=Integer.valueOf(strings[2]); } public void print() { System.out.println("s="+s); System.out.println("i1="+i1); System.out.println("i2="+i2); System.out.println("i3="+i3); } }
运行结果: 查看是否允许带有可变数量的参数:true 该构造方法的入口参数类型依次为: class [Ljava.lang.String; 该构造方法可能抛出的异常类型为: class java.lang.NumberFormatException s=null i1=100 i2=200 i3=300 查看是否允许带有可变数量的参数:false 该构造方法的入口参数类型依次为: class java.lang.String int 该构造方法可能抛出的异常类型为: s=4 i1=7 i2=0 i3=0 查看是否允许带有可变数量的参数:false 该构造方法的入口参数类型依次为: 该构造方法可能抛出的异常类型为: 在创建对象时抛出异常,下面执行setAccessible()方法 该构造方法使用private修饰 s=null i1=0 i2=0 i3=0
III. 访问成员变量:在通过下列一组方法访问成员变量时,将返回field类型的对象或数组,每个Field对象代表一个成员变量,利用Field对象可以操纵相应的成员变量
1||| getFields()
2||| getField(String name)
3||| getDeclaredFields()
4||| getDeclaredField(String name)
如果是访问指定的成员变量,可以通过该成员变量的名称来访问。例如,访问一个名称为birthday的成员变量,访问方法如下: object.getDeclaredField(“birthday”); Field类常用的方法有:
1||| getName():获得该成员变量的名称
2||| getType():获得表示该成员变量类型的Class对象
3||| get(Object obj):获得指定对象obj中成员变量的值,返回值为Object型
4||| set(Object obj,Object value):将指定对象obj中成员变量的值设置为value
5||| getInt(Object obj):获得指定对象obj中类型为int的成员变量的值
6||| setInt(Object obj,int i):将指定对象中类型为int的成员变量的值设置为i
7||| getFloat(Object obj):获得指定对象中类型为float的成员变量的值
8||| setFloat(Object obj,float f):将指定对象obj中类型为float的成员变量的值设置为f
9||| getBoolean(Object obj):获得指定对象obj中类型为boolean的成员变量的值
10||| setBoolean(Object obj,boolean z):将指定对象obj中类型为boolean的成员变量的值设置为z
11||| setAccessible(boolean flag):此方法可以设置是否忽略权限限制直接访问private等私有权限的成员变量
12||| getModifiers():获得可以解析出该成员变量所采用修饰符的整数
实例代码: package com.REFLECT; 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 i=0;i< declaredFields.length;i++) { //遍历成员变量 Field field=declaredFields[i]; System.out.println("名称为:"+field.getName()); //获得成员变量名称 Class fieldType=field.getType(); //获得成员变量类型 System.out.println("类型为:"+fieldType); boolean flag=true; while(flag) { //如果该成员变量的访问权限为private,则抛出异常(不允许访问) try { flag=false; System.out.println("修改前的值为:"+field.get(example)); if(fieldType.equals(int.class)) { //判断成员变量的类型是否为int型 System.out.println("利用方法setInt()修改成员变量的值:"); field.setInt(example,168); } else if (fieldType.equals(float.class)) { // 判断成员变量的类型是否为float型 System.out.println("利用方法setFloat()修改成员变量的值"); field.setFloat(example,86.8F); } else if (fieldType.equals(boolean.class)) { System.out.println("利用方法setBoolean()修改成员变量的值"); field.setBoolean(example,true); }else { System.out.println("利用set()方法修改成员变量的值"); field.set(example,"RNW"); //可以为各种类型的成员变量赋值 } System.out.println("修改后的值为:"+field.get(example)); }catch(Exception e) { System.out.println("在设置成员变量值时抛出异常,下面执行setAccessible()方法!"); field.setAccessible(true); flag=true; } } System.out.println(); } } }
package com.REFLECT; public class Example_02 { int i; public float f; protected boolean b; private String s; }
运行结果: 名称为:i 类型为:int 修改前的值为:0 利用方法setInt()修改成员变量的值: 修改后的值为:168 名称为:f 类型为:float 修改前的值为:0.0 利用方法setFloat()修改成员变量的值 修改后的值为:86.8 名称为:b 类型为:boolean 修改前的值为:false 利用方法setBoolean()修改成员变量的值 修改后的值为:true 名称为:s 类型为:class java.lang.String 在设置成员变量值时抛出异常,下面执行setAccessible()方法! 修改前的值为:null 利用set()方法修改成员变量的值 修改后的值为:RNW 进程已结束,退出代码0
IV. 访问方法:在通过下列一组方法访问方法时,将返回Method类型的对象或数组。每个Method对象代表一个方法,利用Method对象可以操纵相应的方法。
1||| getMethods( )
2||| getMethod(String name,Class<?>...parameterTypes)
3||| getDeclaredMethods( )
4||| getDeclaredMethod(String name,Class<?>...paremeterTypes)
如果是访问指定的方法,需要根据该方法的名称和入口参数的类型来访问。例如,访问一个名称为print、入口参数类型依次为String和int型的方法,通过下面两种方式均可实现。
1||| objectClass.getDeclaredMethod("print",String.class,int.class);
2||| objectClass.getDeclaredMethod("print",new Class[ ]{String.class,int.class});
Method类的常用方法
1||| getName():获得该方法的名称
2||| getParameterTypes():按照声明顺序以Class数组的形式获得该方法的各个参数的类型
3||| getReturnType():以Class对象的形式获得该方法的返回值的类型
4||| getExceptionTypes():以Class数组的形式获得该方法可能抛出的异常类型
5||| invoke(Object obj,Object...args):利用指定参数args执行指定对象obj中的该方法,返回值为Object型
6||| isVarArgs():查看该构造方法是否允许带有可变数量的参数,如果允许返回true,否则返回false
7||| getModifiers():获得可以解析出该方法所采用修饰符的整数
实例代码: package com.REFLECT; 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 i=0;i< declaredMethods.length;i++) { Method method=declaredMethods[i]; System.out.println("名称为:"+method.getName()); //获得方法名称 System.out.println("是否循序带有可变数量的参数"+method.isVarArgs()); System.out.println("入口参数类型依次为:"); Class[] parameterTypes=method.getParameterTypes(); //获得所有参数类型 for (int j=0;j<parameterTypes.length;j++) { System.out.println(parameterTypes[j]); } System.out.println("返回值类型为: "+method.getReturnType()); //获得返回值类型 System.out.println("可能抛出的异常类型有:"); Class[] exceptionType=method.getExceptionTypes(); //获得方法可能抛出的所有异常类型 for (int k=0;k< exceptionType.length;k++) { System.out.println(exceptionType[k]); } boolean flag=true; while(flag) { //如果方法的访问权限为private则抛出异常 try{ flag=false; if("staticMethod".equals(method.getName())) { method.invoke(example); //执行没有入口参数的方法 } else if ("publicMethod".equals(method.getName())) { System.out.println("返回值为: "+method.invoke(example,168)); //执行方法 } else if ("protectedMethod".equals(method.getName())) { System.out.println("返回值为: "+method.invoke(example,"8",6)); } else if ("privateMethod".equals(method.getName())) { Object[] parameters=new Object[]{ new String[]{"H","D","S"}}; //定义二维数组 System.out.println("返回值为: "+method.invoke(example,parameters)); } }catch(Exception e) { System.out.println("在执行方法时抛出异常,下面执行setAccessible()方法"); method.setAccessible(true); flag=true; } } System.out.println(); } } }
package com.REFLECT; 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(); for (int i=0;i< strings.length;i++) { stringBuffer.append(strings[i]); } return stringBuffer.toString(); } }
运行结果: 名称为:protectedMethod 是否循序带有可变数量的参数false 入口参数类型依次为: class java.lang.String int 返回值类型为: int 可能抛出的异常类型有: class java.lang.NumberFormatException 执行protectedMethod()方法 返回值为: 14 名称为:publicMethod 是否循序带有可变数量的参数false 入口参数类型依次为: int 返回值类型为: int 可能抛出的异常类型有: 执行publicMethod()方法 返回值为: 16800 名称为:privateMethod 是否循序带有可变数量的参数true 入口参数类型依次为: class [Ljava.lang.String; 返回值类型为: class java.lang.String 可能抛出的异常类型有: 在执行方法时抛出异常,下面执行setAccessible()方法 执行privateMethod()方法 返回值为: HDS 名称为:staticMethod 是否循序带有可变数量的参数false 入口参数类型依次为: 返回值类型为: void 可能抛出的异常类型有: 执行staticMethod()方法
在反射中执行具有可变数量的参数的构造方法时,需要将入口参数定义成二维数组
二、 使用Annotation功能
Java中提供了Annotation功能,该功能可用于类、构造方法、成员变量、方法、参数等的声明中。该功能并不影响程序的运行,但是会对编译器警告等辅助工具产生影响。
1. 定义Annotation类型:在定义Annotation类型时,也需要用到用来定义接口的interface关键字,但需要在interface关键字前加一个“@”符号,即定义Annotation类型的关键字为@interface,这个关键字的隐含意思是继承了java.lang.annotation.Annotation接口。示例如下: public @interface NoMemberAnnotation{ }
上面定义的Annotation类型@NoMemberAnnotation未包含任何成员,这样的Annotation类型被称为marker annotation。下面的代码定义了一个只包含一个成员的Annotation类型。下面定义一个只包含一个成员的Annotation类型。 public @interface OneMemberAnnotation{ String value( ); } 下面的代码定义了一个包含多个成员的Annotation类型 public @interface MorememberAnnotation{ String describe(); Class type(); }
在为Annotation类型定义成员时,也可以为成员设置默认值。例如,下面的代码在定义Annotation类型时就为成员设置了默认值。 public @interface DefaultValueAnnotation { String describe( )default"<默认值>" Class type( )default void class; }
1||| String:成员类型。可用的成员类型有String、Class、primitive、enumerated和annotation,以及所列类型的数组
2||| value:成员名称。如果在所定义的Annotation类型中只包含一个成员,通常将成员名称命名为value
在定义Annotation类型时,还可以通过Annotation类型@Target来设置Annotation类型适用的程序元素种类。如果未设置@Target,则表示适用于所有程序元素。枚举类ElementType中的枚举常量用来设置@Target,如下所示
1||| ANNOTATION_TYPE:表示用于Annotation类型
2||| TYPE:表示用于类、接口和枚举,以及Annotation类型
3||| CONSTRUCTOR:表示用于构造方法
4||| FIELD:表示用于成员变量和枚举常量
5||| METHOD:表示用于方法
6||| PARAMETER:表示用于参数
7||| LOCAL_VARIABLE:表示用于局部变量
8||| PACKAGE:表示用于包
通过Annotation类型@Retention可以设置Annotation的有效范围。枚举类RetentionPolicy中的枚举常量用来设置@Retention,如右所示。如果未设置@Retention,Annotation的有效范围为枚举常量CLASS表示的范围。
1||| SOURCE:表示不编译Annotation到类文件中,有效范围最小
2||| CLASS:表示编译Annotation到类文件中,但是在运行时不加载Annotation到JVM中
3||| RUNTIME:表示运行时加载Annotation到JVM中,有效范围最大
实例代码: package com.REFLECT; import java.lang.annotation.*; @Target(ElementType.CONSTRUCTOR) //用于构造方法 @Retention(RetentionPolicy.RUNTIME) //在运行时加载Annotation到JVM中 public @interface Construct_Annotation{ String value()default"默认构造方法"; //定义一个具有默认值的String型成员 }
package com.REFLECT; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @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型成员 }
package com.REFLECT; public class Record { @Field_Method_Parameter_Annotation(describe="编号",type=int.class) //注释字段 int id; @Field_Method_Parameter_Annotation(describe="姓名",type=String.class) String name; @Construct_Annotation() //采用默认值注释构造方法 public Record() { } @Construct_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; } }
2. 访问Annotation信息:如果在定义Annotation类型时将@Retention设置为RetentionPolicy.RUNTIME,那么在运行程序时通过反射就可以获取到相关的Annotation信息,如获取构造方法、字段和方法的Annotation信息。 类Constructor、Field和Method均继承了AccessibleObject类,在AccessibleObject中定义了3个关于Annotation的方法,其中方法isAnnotationPresent(Class<? extends Annotation> annotationClass)用来查看是否添加了指定类型的Annotation,如果是则返回true,否则返回false;方法getAnnotation(Class<T>annotationClass)用来获得指定类型的Annotation,如果存在则返回相应的对象,否则返回null;方法getAnnotations()用来获得所有的Annotation,该方法将返回一个Annotation数组。 在类Constructor和Method中还定义了方法getParameterAnnotations(),用来获得为所有参数添加的Annotation,将以Annotation类型的二维数组返回,在数组中的顺序与声明的顺序相同,如果没有参数则返回一个长度为0的数组;如果存在未添加Annotation的参数,将用一个长度为0的嵌套数组占位。
构造方法的注释实例代码: package com.REFLECT; import java.lang.annotation.*; @Target(ElementType.CONSTRUCTOR) //用于构造方法 @Retention(RetentionPolicy.RUNTIME) //在运行时加载Annotation到JVM中 public @interface Construct_Annotation{ String value()default"默认构造方法"; //定义一个具有默认值的String型成员 }
字段、方法、参数的注释实例代码: package com.REFLECT; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @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型成员 }
Record类: package com.REFLECT; public class Record { @Field_Method_Parameter_Annotation(describe="编号",type=int.class) //注释字段 int id; @Field_Method_Parameter_Annotation(describe="姓名",type=String.class) String name; @Construct_Annotation() //采用默认值注释构造方法 public Record() { } @Construct_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; } }
访问构造方法及其包含参数的实例代码: package com.REFLECT; import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; public class Visit_Construct_Parameter { public static void main(String[] args) { Record record=new Record(); Class recordC=record.getClass(); Constructor[] declaredConstructors=recordC.getDeclaredConstructors(); for (int i=0;i< declaredConstructors.length;i++) { Constructor constructor=declaredConstructors[i]; //遍历构造方法 if (constructor.isAnnotationPresent(Construct_Annotation.class)){//查看是否具有指定类型的注释 Construct_Annotation ca=(Construct_Annotation) constructor.getAnnotation(Construct_Annotation.class); //获得注释信息 System.out.println(ca.value()); //输出注释信息 } Annotation[][] parameterAnnotations=constructor.getParameterAnnotations(); //获得参数的注释 for (int j=0;j< parameterAnnotations.length;j++) { //获得指定参数注释的长度 int length= parameterAnnotations[j].length; if(length==0) { System.out.println("\t未添加Annotation的参数"); }else for (int k=0;k<length;k++) { //获得参数的注释 Field_Method_Parameter_Annotation pa= (Field_Method_Parameter_Annotation) parameterAnnotations[j][k]; System.out.print("\t"+pa.describe()); //获得参数描述 System.out.println("\t"+pa.type()); //获得参数类型 } } System.out.println(); } } }
访问字段的实例代码: package com.REFLECT; import java.lang.reflect.Field; public class Visit_Field { public static void main(String[] args) { Record record=new Record(); Class recordC=record.getClass(); Field[] declaredFields=recordC.getDeclaredFields(); //获得所有字段 for (int i=0;i< declaredFields.length;i++) { Field field=declaredFields[i]; //遍历字段 if(field.isAnnotationPresent(Field_Method_Parameter_Annotation.class)) { //查看是否具有指定类型的注释 Field_Method_Parameter_Annotation fa =field.getAnnotation(Field_Method_Parameter_Annotation.class); System.out.println("\t"+fa.describe()); //获得字段的描述 System.out.println("\t"+fa.type()); //获得字段的类型 } } } }
访问方法及其包含参数的信息实例代码: package com.REFLECT; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.Method; public class Visit_Method { public static void main(String[] args) { Record record=new Record(); Class recordC=record.getClass(); Method[] methods=recordC.getDeclaredMethods(); //获得所有方法 for (int i=0;i< methods.length;i++) { //遍历方法 Method method=methods[i]; if(method.isAnnotationPresent(Field_Method_Parameter_Annotation.class)) { //获得指定的注释 Field_Method_Parameter_Annotation ma=method .getAnnotation(Field_Method_Parameter_Annotation.class); System.out.println(ma.describe()); //获得方法的描述 System.out.println(ma.type()); //获得方法的返回值类型 } Annotation[][] parameterAnnotations=method.getParameterAnnotations(); //获得参数的注释 for (int j=0;j< parameterAnnotations.length;j++) { int length= parameterAnnotations[j].length; if (length==0) { System.out.println("未添加Annotation参数"); } else for (int k=0;k<length;k++) { //获得指定类型的注释 Field_Method_Parameter_Annotation pa=(Field_Method_Parameter_Annotation) parameterAnnotations[j][k]; System.out.println(pa.describe()); System.out.println(pa.type()); } } System.out.println(); } } }