Java from entry to the master Chapter 16 reflection

table of Contents

Class-based reflective

Access constructor

Access member variables

Access Methods

Use the Annotation function

Annotation type definitions

Annotation information access


Class-based reflective

java.lang.reflect

All classes inherit the Object class defines a method getClass Object class, the method returns a Class object type, the object information by using the main class Class accessible. Member variables and methods getFields () and getMethods () method in order to obtain permission for the public, including inherited from a parent class member variables and methods. getDeclaredFields () and getDeclaredMethods () to get all member variables and methods defined in the class only.

Access constructor

The method of construction by accessing the table above, return Constructor object or array type . Each object represents a constructor Constructor. Each Constructor object can be manipulated using the appropriate constructor.

package ex16_reflect;

public class Example_01 {
    String s;
    int i;
    int i2;
    int i3;

    private Example_01() {
    }

    protected Example_01(String s, int i) {
        this.s = s;
        this.i = i;
    }

    public Example_01(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);
    }
}
//============================================================================

package ex16_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 {
                    if (i == 2) {
                        example2 = (Example_01) constructor.newInstance();
                    } else if (i == 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) {
                    //该构造方法权限为private,默认不允许使用反射利用newInstance()创建对象,先执行setAccessible(true);则允许创建
                    System.out.println("在创建对象时抛出异常,下面执行setAccessible()方法");  
                    constructor.setAccessible(true);
                }
            }
            if (example2 != null) {
                example2.print();
                System.out.println();
            }
        }
    }
}

Access member variables

Field return type or array of objects, each object represents a member variable Field , the object can be manipulated using Filed corresponding member variable.

package ex16_reflect;

public class Example_02 {
    int i;
    public float f;
    protected boolean b;
    private String s;
}

//=========================================================

package ex16_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();  //使用getClass()获得Class对象
        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 isTrue = true;
            while (isTrue) {
                //如果该成员变量的访问权限为private,则抛出异常,则不允许访问
                try {
                    isTrue = 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, 99.9F);
                    } else if (fieldType.equals(boolean.class)) {
                        System.out.println("利用方法setBoolean()修改成员变量的值");
                        field.setBoolean(example, true);
                    } else {
                        System.out.println("利用方法set()修改成员变量的值");
                        field.set(example, "MWQ");  //可以为各种类型的成员变量赋值
                    }
                    System.out.println("修改后的值:" + field.get(example));
                } catch (Exception e) {
                    //String s;权限为private,需要先设置setAccessible()再修改
                    System.out.println("在设置成员变量时抛出异常,下面执行setAccessible()方法");
                    field.setAccessible(true);
                    isTrue = true;
                }
            }
            System.out.println("---------------------------");
        }


        Field field = declaredFields[3];
        try {
            field.set(example, "hi");
            System.out.println(field.get(example));
            field.setAccessible(false);  //修改过一次后就一直是true了
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}

Access Methods

Through getMethod () access method and other methods, Method, return () array and an object type. Each object represents a method of Method. Method object can be manipulated using a corresponding method.

package ex16_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();

    }
}
//============================================================

package ex16_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[] exceptionTypes = method.getExceptionTypes();  //可能抛出的异常类型
            for (int j = 0; j < exceptionTypes.length; j++) {
                System.out.println(" " + exceptionTypes[j]);
            }

            boolean isTrue = true;
            while (isTrue) {
                //如果方法访问权限为private抛出异常,不允许访问
                try {
                    isTrue = false;
                    if ("staticMethod".equals(method.getName())) {
                        method.invoke(example);  //执行没有入口参数的方法staticMethod
                    } 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) {
                    //privateMethod()权限为private需要先setAccessible(true);才可以访问
                    System.out.println("在执行方法时出现异常,执行下面的setAccessible()方法");
                    method.setAccessible(true);
                    isTrue = true;
                }
            }
            System.out.println();
        }
    }
}

Use the Annotation function

Annotation type definitions

  • Use @interface, the implied meaning of this keyword is inherited java.lang.annotation.Annotation Interface
  • Use @Annotation, set the element type members Annotation type used, the use of enumeration constant set of enumeration class ElementType
  • @Retention used, provided Annotation effective range, enum constant is set in the enumeration class RetentionPolicy

package ex16_reflect;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.CONSTRUCTOR)  //用于构造方法
@Retention(RetentionPolicy.RUNTIME)  //在运行时加载Annotation到JVM中
public @interface Constructor_Annotation {
    String value() default "默认构造方法";  //定义一个具有默认值的String型成员
}
package ex16_reflect;

import java.lang.annotation.*;
//用于字段、方法、参数
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})

//在运行时加载Annotation到JVM中
@Retention(RetentionPolicy.RUNTIME)

public @interface Field_Method_Parameter_Annotation {
    String describle();               //定义一个没有默认值的String型成员
    Class type() default void.class;  //定义一个具有默认值的Class型成员
}

Annotation information access

When defining Annotation type, @ Retention RetentionPolicy.RUNTIME set, then the program is run by reflection can be obtained Annotation related information, such as configuration information acquiring Annotation methods, fields, methods.

  • Constructor, Field, Method AccessableObject are inherited class, three methods are defined in the Annotation on the AccessibleObject
    • isAnnotationPresent (Class <? extends Annotation> annotationClass); see if the addition of the specified type Annotation
    • getAnnotation (Class <T> annotationClass); the Annotation for the specified type, returns the corresponding object is present, there is no return null
    • getAnnotations (); return all Annotation, returns an array
  • Method in Constructor and also defines the methods getParameterAnnotations (); Annotation added to obtain all the parameters, will return Annotation type two-dimensional array, in the same order as the order of declaration in the array, no parameters of length 0 is returned array; No Annotation nested array of length parameter placeholder 0

Using the previously defined in the Record Type Annotation class @Constructor_Annotation and @Field_Method_Parameter_Annotation.

package ex16_reflect;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class Record {
    @Field_Method_Parameter_Annotation(describle = "编号", type = int.class)
    int id;
    @Field_Method_Parameter_Annotation(describle = "姓名", type = String.class)
    String name;

    @Constructor_Annotation()
    public Record() {
    }

    @Constructor_Annotation("立即初始化构造方法")
    public Record(
            @Field_Method_Parameter_Annotation(describle = "编号", type = int.class) int id,
            @Field_Method_Parameter_Annotation(describle = "姓名", type = String.class) String name) {
        this.id = id;
        this.name = name;
    }

    @Field_Method_Parameter_Annotation(describle = "获得编号", type = int.class)
    public int getId() {
        return id;
    }

    @Field_Method_Parameter_Annotation(describle = "设置编号")
    public void setId(
            @Field_Method_Parameter_Annotation(describle = "编号", type = int.class) int id) {
        this.id = id;
    }

    @Field_Method_Parameter_Annotation(describle = "获得姓名", type = String.class)
    public String getName() {
        return name;
    }

    @Field_Method_Parameter_Annotation(describle = "设置姓名")
    public void setName(
            @Field_Method_Parameter_Annotation(describle = "姓名", type = String.class) String name) {
        this.name = name;
    }

    public static void main(String[] args) {
        Record record = new Record();
        Class recordC = record.getClass();

        //========================访问构造方法(Constructor)====================================
        System.out.println("=====访问构造方法(Constructor)=======");
        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(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.println("  " + pa.describle());  //获得参数描述
                        System.out.println("  " + pa.type());       //获得参数类型
                    }
                }
            }
            System.out.println();
        }

        //============================访问字段(Field)=====================================
        System.out.println("=======访问字段(Field)==========");
        Field[] declaredFileds = recordC.getDeclaredFields();  //获得所有字段
        for (int i = 0; i < declaredFileds.length; i++) {
            Field field = declaredFileds[i];
            //查看是否具有指定类型的注释
            if (field.isAnnotationPresent(Field_Method_Parameter_Annotation.class)) {
                //获得指定类型的注释
                Field_Method_Parameter_Annotation fa = field
                        .getAnnotation(Field_Method_Parameter_Annotation.class);
                System.out.println("  " + fa.describle());  //获得字段的描述
                System.out.println("  " + fa.type());       //获得字段的类型
            }
            System.out.println();
        }

        //============================访问方法(Method)及包含参数的Annotation信息================
        System.out.println("===访问方法(Method)及包含参数的Annotation信息===");
        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.describle());  //获得方法的描述
                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.describle());  //获得参数描述
                        System.out.println("  " + pa.type());       //获得参数类型
                    }
                }
            }
            System.out.println();

        }

    }

}

 

 

 

 

 

 

 

 

 

 

 

 

Published 46 original articles · won praise 0 · Views 1019

Guess you like

Origin blog.csdn.net/weixin_37680513/article/details/103560581