Java--Class类与反射+Annotation注解

        通过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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

chuntian_tester

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值