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 "";
}