JVM · Java虚拟机原理 · JVM上语言·框架· 生态系统Java

Class类与JAVA反射

2020-04-22  本文已影响0人  relax_小罗罗

Class类与JAVA反射
通过反射可以访问的主要信息

包路径

getPackage() Package对象 获取该对象的存放路径;

类名称

getName() String对象 获得该类的名称;

继承类

getSuperclass() Class对象 获得该类的继承的类;

实现接口类

getInterface() Class型数组 获取该类实现的所有接口;

构造方法

getConstructors() Constructors型数组 获得所有权限为public的构造方法;
getConstructor(Class<?>...parameterTypes) Constructors 获得权限为public的指定构造方法;
getDeclaredConstructor() Constructors型数组 获得所有狗做方法,按生命顺序返回;
getDeclaredConstructor(Class<?>...parameterTypes) Constructors对象 获得指定构造法方法;

方法

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;

在通过getFields()和getMethods()方法时,将包含从超类继承道德成员变量和方法;而通过 getDeclaredFields() 和 getDeclaredMethods() 只能获得在奔雷定义的所有成员变量和方

访问构造方法

isVarArgs() 查看该构造方法是否允许带有可变数量的参数,如果允许则返回true,否则false;
getParameterTypes() 按照声明顺序以Class数组的形式获得该构造方法的各个参数类型;
getExceptionTypes() 以Class数组的形式获得该构造方法可能抛出的异常类型。
newInstance(Object...initargs) 通过该构造方法利用指定构造方法创建一个该类的对象,如果未设置,则采用无参默认构造函数
setAccessible(boolean flag) 针对private的构造方法 限制性该方法设置为true,则可以使用newInstance(Object...initargs)创建对象;
getModifiers() 获得可以解析出该构造方法所采用修饰符的整数;

public class ClassEntity {
    String s;
    int i, i2, i3;
    private ClassEntity() {
    }
    protected ClassEntity(String s, int i) {
        this.s = s;
        this.i = i;
    }
    public ClassEntity(String... strings) throws NumberFormatException {
        if (0 < strings.length)
            i = 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("i=" + i);
        System.out.println("i2=" + i2);
        System.out.println("i3=" + i3);
    }
}
  public static void main(String[] args) {

        ClassEntity example = new ClassEntity("10", "20", "30");
        Class<? extends ClassEntity> 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]);
            }
            ClassEntity example2 = null;
            while (example2 == null) {
                try {
                    if (i == 2)
                        example2 = (ClassEntity) constructor.newInstance();
                    else if (i == 1)
                        example2 = (ClassEntity) constructor.newInstance("7", 5);
                    else {
                        Object[] parameters = new Object[] { new String[] {
                                "100", "200", "300" } };
                        example2 = (ClassEntity) constructor
                                .newInstance(parameters);
                    }
                } catch (Exception e) {
                    System.out.println("在创建对象时抛出异常,下面执行setAccessible()方法");
                    constructor.setAccessible(true);
                }
            }
            if(example2!=null){
                example2.print();
                System.out.println();
            }
        }
    }

访问成员变量

getName() 获得该成员变量的名称;
getType() 获得表示该成员变量类型的Class对象;
get(Object o) 获得指定对象obj中成员变量的值,返回Object类型;
Set(Object o,Object value) 将指定对象obj成员变量设置value值;
getInt(Object o) ;
SetInt(Object o,int value) ;
...
setAccessible(boolean flage) 此方法可以设置是否忽略权限限制直接访问private等私有权限的成员变量;
getModifiers() 获得可以解析出该成员变量所采用修饰符的整数;

public class ClassFeildEntity {
    int i;
    public float f;
    protected boolean b;
    private String s;
   // private ClassEntity classEntity;
}
 public static void main(String[] args) {
        ClassFeildEntity example = new ClassFeildEntity();
        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 isTurn = true;
            while (isTurn) {
                // 如果该成员变量的访问权限为private,则抛出异常,即不允许访问
                try {
                    isTurn = false;
                    // 获得成员变量值
                    System.out.println("修改前的值为:" + field.get(example));
                    // 判断成员变量的类型是否为int型
                    if (fieldType.equals(int.class)) {
                        System.out.println("利用方法setInt()修改成员变量的值");
                        field.setInt(example, 168); // 为int型成员变量赋值
                        // 判断成员变量的类型是否为float型
                    } else if (fieldType.equals(float.class)) {
                        System.out.println("利用方法setFloat()修改成员变量的值");
                        // 为float型成员变量赋值
                        field.setFloat(example, 99.9F);
                        // 判断成员变量的类型是否为boolean型
                    } else if (fieldType.equals(boolean.class)) {
                        System.out.println("利用方法setBoolean()修改成员变量的值");
                        // 为boolean型成员变量赋值
                        field.setBoolean(example, true);
                    } else {
                        System.out.println("利用方法set()修改成员变量的值");
                        // 可以为各种类型的成员变量赋值
                        field.set(example, "MWQ");
                    }
                    // 获得成员变量值
                    System.out.println("修改后的值为:" + field.get(example));
                } catch (Exception e) {
                    System.out.println("在设置成员变量值时抛出异常,"
                            + "下面执行setAccessible()方法!");
                    field.setAccessible(true); // 设置为允许访问
                    isTurn = true;
                }
            }
            System.out.println();
        }
    }

访问方法

getName() 获得该方法名称;
getParameterTypes() 按照声明顺序以Class数组的形式获得该方法的各个参数类型;
getReturnType() 以Class对象的形式获得该方法的返回值的类型;
getExceptionTypes() 以class数组的形式获得该方法可能跑出的异常类型;
invoke(Object o,Object...args) 利用指定参数args执行指定对象obj中的该方法,赶回值为Object 型;
isVarArgs() 查看该构造方法是够允许带有可变数量的参数,如果允许则返回true,否则返回false;
getModifiers() 获得可以解析出该方法所采用修饰符的整数;
setAccessible(boolean flage) ;

public class ClassMethodEntity {
    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();
    }
}
  public static void main(String[] args) {
        ClassMethodEntity example = new ClassMethodEntity();
        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[] exceptionTypes = method.getExceptionTypes();
            for (int j = 0; j < exceptionTypes.length; j++) {
                System.out.println(" " + exceptionTypes[j]);
            }
            boolean isTurn = true;
            while (isTurn) {
                // 如果该方法的访问权限为private,则抛出异常,即不允许访问
                try {
                    isTurn = 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, "7", 5)); // 执行方法
                    else if("privateMethod".equals(method.getName())) {
                        Object[] parameters = new Object[] { new String[] {
                                "M", "W", "Q" } }; // 定义二维数组
                        System.out.println("返回值为:"
                                + method.invoke(example, parameters));
                    }
                } catch (Exception e) {
                    System.out.println("在执行方法时抛出异常,"
                            + "下面执行setAccessible()方法!");
                    method.setAccessible(true); // 设置为允许访问
                    isTurn = true;
                }
            }
            System.out.println();
        }
    }

Annotation功能

@Targer的枚举常量
ANNOTATION_TYPE 表示用于annotation类型;
TYPE 表示用于类,接口和枚举,以及annotation类型;
CONSTRUCTOR 表示用于构造方法;
FIELD 表示用于成员变量和枚举常量;
METHOD 表示用于方法;
PARAMETER 表示用于参数;
LOCAL_VARLABLE 表示用于局部变量;
PACKAGE 表示用于包;

@Retention
SOURCE 表示不便于Annotaion到类文件中;
CLASS 表示编译到Annotation类文件中,但是在运行时不加载Annotation到jvm中;
RUNTIME 表示在运行时加载Annotation到jvm中;

isAnnotation(Class<?extends Annotation> annotationClass) 用来查看是否添加了指定类型的Annotation;
getAnnotation(Class<T> annotationClass) 用来获得指定类型的Annotation;
getParameterAnnotation() 用来获得所有参数添加的Annotation,将以Annotation类的二维数组返回;

@Target(ElementType.CONSTRUCTOR)
@Retention(RetentionPolicy.RUNTIME)
public @interface Constructor_Annotation {

    String value() default "默认构造方法";
}

@Target( { ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
public @interface Field_Method_Parameter_Annotation {

    String describe();

    Class type() default void.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 = "设置编号")
    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;
    }

}

    public static void main(String[] args) {

        Class recordC = null;
        try {
            recordC = Class.forName("com.luozy.base.ClassDemo.AnnotationDemo.Record");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        System.out.println("------ 构造方法的描述如下 ------");
        Constructor[] declaredConstructors = recordC
                .getDeclaredConstructors(); // 获得所有构造方法
        for (int i = 0; i < declaredConstructors.length; i++) {
            Constructor constructor = declaredConstructors[i]; // 遍历构造方法
            // 查看是否具有指定类型的注释
            if (constructor
                    .isAnnotationPresent(Constructor_Annotation.class)) {
                // 获得指定类型的注释
                Constructor_Annotation ca = (Constructor_Annotation) constructor
                        .getAnnotation(Constructor_Annotation.class);
                System.out.println(constructor.getName()+"构造方法的注释信息------"+ca.value()); // 获得注释信息
            }
            Annotation[][] parameterAnnotations = constructor
                    .getParameterAnnotations(); // 获得参数的注释
            for (int j = 0; j < parameterAnnotations.length; j++) {
                // 获得指定参数注释的长度
                int length = parameterAnnotations[j].length;
                if (length == 0) // 如果长度为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.print("    " + pa.describe()); // 获得参数描述
                        System.out.println("    " + pa.type()); // 获得参数类型
                    }
            }
            System.out.println();
        }

        System.out.println();

        System.out.println("-------- 字段的描述如下 --------");
        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.print("    " + fa.describe()); // 获得字段的描述
                System.out.println("    " + fa.type()); // 获得字段的类型
            }
        }

        System.out.println();

        System.out.println("-------- 方法的描述如下 --------");
        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) // 如果长度为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.print("    " + pa.describe()); // 获得参数的描述
                        System.out.println("    " + pa.type()); // 获得参数的类型
                    }
            }
            System.out.println();
        }

    }
上一篇 下一篇

猜你喜欢

热点阅读