Reflection

package com.tenpay.risk.aml.cdd.batch.apisvr.core.basic;

import lombok.Data;
import org.junit.jupiter.api.Test;

import java.io.Serializable;
import java.lang.annotation.*;
import java.lang.reflect.*;
import java.util.ArrayList;
import java.util.List;

/**
 * 1、获取指定的构造函数,并创建新的实例
 * 2、获取私有成员方法并调用
 * 3、获取静态方法并调用
 * 4、访问私有字段
 * 5、访问注解Annotation
 * 6、访问成员变量的泛型、方法参数的泛型、方法返回值的泛型  method.getGenericReturnType,listField.getGenericType(),setListMethod.getGenericParameterTypes()
 */
@Data
public class ReflectionTest {

    @Test
    void test() throws Exception{

        /**获取类的Class*/
        Class<Person> personClass = Person.class;
        System.out.println(personClass);
        System.out.println(personClass.getName());
        System.out.println(personClass.getSimpleName());
        System.out.println(personClass.getModifiers());

        /**获取所有构造函数 Declared*/
        Constructor<?>[] declaredConstructors = personClass.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor);
        }

        /**指定具体的构造函数创建实例*/
        Constructor<Person> declaredConstructor = personClass.getDeclaredConstructor(Integer.class, String.class);
        Person binfire = declaredConstructor.newInstance(1, "binfire");
        System.out.println(binfire);

        /**访问私有方法*/
        Method sayHello = personClass.getDeclaredMethod("sayHello");
        sayHello.setAccessible(true);
        sayHello.invoke(binfire);

        /**访问静态方法*/
        Method sayHelloMessage = personClass.getDeclaredMethod("sayHelloMessage",String.class,Integer.class,String.class);
        sayHelloMessage.setAccessible(true);
        sayHelloMessage.invoke(null,"binfire",30,"您好");

        /**访问字段*/
        Field[] declaredFields = personClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField);
        }
        Field name = personClass.getDeclaredField("name");
        name.setAccessible(true);
        name.set(binfire,"中国");
        Object o = name.get(binfire);
        System.out.println(o);
        Field age = personClass.getDeclaredField("age");
        age.setAccessible(true);
        age.setInt(binfire,123);
        int anInt = age.getInt(binfire);
        System.out.println(anInt);

        /**Annotation注解*/
        if(name.isAnnotationPresent(MyAnnotation.class)){
            MyAnnotation declaredAnnotation = name.getDeclaredAnnotation(MyAnnotation.class);
            if(declaredAnnotation!=null){
                System.out.println(declaredAnnotation.testA()+":"+declaredAnnotation.testB());
            }

        }




    }

    @Test
    void testGenerialInfo() throws NoSuchMethodException {
        getMethodReturnValueGeneric();
    }

    /**
     * 获取方法返回值的泛型类型信息
     *
     * @throws NoSuchMethodException
     */
    public void getMethodReturnValueGeneric() throws NoSuchMethodException {
        // 获取名为"getList"的方法,在MyClass类中
        Method getListMethod = MyClass.class.getMethod("getList");
        // 获取返回值类型,getGenericReturnType()会返回值带有泛型的返回值类型
        Type genericReturnType = getListMethod.getGenericReturnType();
        // 但我们实际上需要获取返回值类型中的泛型信息,所以要进一步判断,即判断获取的返回值类型是否是参数化类型ParameterizedType
        if (genericReturnType instanceof ParameterizedType) {
            // 如果要使用ParameterizedType中的方法,必须先强制向下转型
            ParameterizedType type = (ParameterizedType) genericReturnType;
            // 获取返回值类型中的泛型类型,因为可能有多个泛型类型,所以返回一个数组
            Type[] actualTypeArguments = type.getActualTypeArguments();
            // 循环数组,遍历每一个泛型类型
            for (Type actualTypeArgument : actualTypeArguments) {
                Class typeArgClass = (Class) actualTypeArgument;
                System.out.println("成员方法返回值的泛型信息:" + typeArgClass);
            }
        }
    }

    /**
     * 获取类中成员变量的泛型类型信息
     *
     * @throws NoSuchFieldException
     */
    public static void getMemberVariablesGeneric() throws NoSuchFieldException {
        // 获取MyTestClass类中名为"list"的字段
        Field listField = MyClass.class.getField("list");
        // 获取该字段的类型信息,getGenericType()方法能够获取带有泛型的类型信息
        Type genericType = listField.getGenericType();
        // 但我们实际上需要获取返回值类型中的泛型信息,所以要进一步判断,即判断获取的返回值类型是否是参数化类型ParameterizedType
        if (genericType instanceof ParameterizedType) {
            ParameterizedType parameterizedType = (ParameterizedType) genericType;
            // 获取成员变量的泛型类型信息
            Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
            for (Type actualTypeArgument : actualTypeArguments) {
                Class fieldArgClass = (Class) actualTypeArgument;
                System.out.println("成员变量的泛型信息:" + fieldArgClass);
            }
        }
    }

    /**
     * 获取方法参数的泛型类型信息
     *
     * @throws NoSuchMethodException
     */
    public static void getMethodParametricGeneric() throws NoSuchMethodException {
        // 获取MyTestClass类中名为"setList"的方法
        Method setListMethod = MyClass.class.getMethod("setList", List.class);
        // 获取该方法的参数类型信息(带有泛型)
        Type[] genericParameterTypes = setListMethod.getGenericParameterTypes();
        // 但我们实际上需要获取返回值类型中的泛型信息,所以要进一步判断,即判断获取的返回值类型是否是参数化类型ParameterizedType
        for (Type genericParameterType : genericParameterTypes) {
            ParameterizedType parameterizedType = (ParameterizedType) genericParameterType;
            // 获取成员方法参数的泛型类型信息
            Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
            for (Type actualTypeArgument : actualTypeArguments) {
                Class realType = (Class) actualTypeArgument;
                System.out.println("成员方法参数的泛型信息:" + realType);
            }
        }
    }

}


class MyClass {
    // 带有泛型的成员变量
    public List<Object> list = new ArrayList<>();

    // 方法返回值中带有泛型
    public List<Object> getList() {
        return list;
    }

    // 方法参数带有泛型
    public void setList(List<Object> list) {
        this.list = list;
    }
}


@Data
class Person implements Cloneable, Serializable {

    /**
     * default VersionUID
     */
    private static final long serialVersionUID = 1L;

    private int age;

    @MyAnnotation(testA = "123",testB = "456")
    private String name;

    private Person(){
        this.age=0;
        this.name=null;
    }

    public Person(Integer age, String name) {
        this.setAge(age);
        this.setName(name);
    }

    private void sayHello(){
        System.out.println("say hello");
    }

    private static void sayHelloMessage(String name,Integer age,String message){
        System.out.printf("%s;%d;%s;%n",name,age,message);
    }

    public int getResult(int[] array){
        int sum=0;
        for(int e:array){
            sum=e+sum;
        }
        return sum;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    @Override
    public String toString() {
        return String.format("%d:%s", this.getAge(),this.getName());
    }

}


/**
 * 注解 @interface开头
 * 元注解, 标记在注解上的注解
 * @Retention,@Documented,@Target,@Inherited,@Repeatable
 * @Retention: 保留期,
 *
 * RetentionPolicy.CLASS (默认)
 * 注解被编译器在编译阶段写入字节码文件,但它并不会在运行时被加载到 JVM 中
 *RetentionPolicy.RUNTIME
 * 注解被编译器在编译阶段写入字节码文件,而且会在运行时加载到 JVM 中,所以在程序运行时可以获取到它们。
 *
 * @Inherited
 * 继承的子类同样继承
 *
 * 注解成员变量:无参的构造函数
 *
 */
@Target({ElementType.METHOD,ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation {
    String testA() default "";
    String testB() default "";
}

  

posted @ 2023-01-06 09:42  yuxuan0802  阅读(36)  评论(0)    收藏  举报