获取运行时类的完整结构

2021-12-02 0 By admin

通过反射机制,我们可以获取到运行时类的完整内部结构,包括:

  1. 属性结构:权限修饰符、数据类型、变量名和注解
  2. 方法结构:权限修饰符、返回值类型、方法名(参数类型1 形参名1,…)、抛出的异常和注解
  3. 构造器:类无参构造器和有参构造器
  4. 父类及父类的泛型
  5. 接口、所在包、注解等

一、提供一个丰富的实体类示例

1.1、结构丰富的Person类

@MyAnnotation(value="java")
public class Person extends Creature<String> implements Comparable<String>,MyInterface{
  private String name;
  int age;
  public int id;
  public Person() {
  }
  @MyAnnotation(value="C++")
  Person(String name){
    this.name = name;
  }
  private Person(String name,int age){
    this.name = name;
    this.age = age;
  }
  @MyAnnotation
  private String show(String nation){
    return nation;
  }
  @Override
  public void info() {
    System.out.println("火星喷子");
  }
  public String display(String play){
    return play;
  }
  @Override
  public int compareTo(String o) {
    return 0;
  }
}

1.2、Creature 父类

import java.io.Serializable;
public abstract class Creature <T> implements Serializable {
  private char gender;
  public double weight;
  private void breath(){
  }
  public void eat(){
  }
}

1.3、MyInterface 接口

public interface MyInterface {
  void info();
}

1.4、MyAnnotation 注解

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.*;
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
  String value() default "hello world";
}

二、获取运行时类的属性结构

获取运行时类的属性结构,包括属性的权限修饰符、数据类型和变量名。

import github2.Person;
import org.junit.Test;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class FieldTest {
  @Test
  public void test(){
    Class clazz = Person.class;
//获取属性结构
//getFields():获取当前运行时类及其父类中声明为public访问权限的属性
    Field[] fields = clazz.getFields();
    for(Field f : fields){
      System.out.println(f);
    }
//getDeclaredFields():获取当前运行时类中声明的所有属性。(不包含父类中声明的属性)
    Field[] declaredFields = clazz.getDeclaredFields();
    for(Field f : declaredFields){
      System.out.println(f);
    }
  }

  @Test
  public void test2(){
    Class clazz = Person.class;
    Field[] declaredFields = clazz.getDeclaredFields();
    for(Field f : declaredFields){
//1.权限修饰符
      int modifier = f.getModifiers();
      System.out.print(Modifier.toString(modifier) + "\t");
//2.数据类型
      Class type = f.getType();
      System.out.print(type.getName() + "\t");
//3.变量名
      String fName = f.getName();
      System.out.print(fName);
    }
  }
}

三、获取运行时类的方法结构

获取运行时类的方法结构,包括方法的权限修饰符、返回值类型、方法名、参数类型、形参名、抛出的异常和注解。

package github3;
import github2.Person;
import org.junit.Test;
import java.lang.reflect.Method;
public class MythodTest {
  @Test
  public void test(){
    Class clazz = Person.class;
//getMethods():获取当前运行时类及其所有父类中声明为public权限的方法
    Method[] methods = clazz.getMethods();
    for(Method m : methods){
      System.out.println(m + "****");
    }
//getDeclaredMethods():获取当前运行时类中声明的所有方法。(不包含父类中声明的方法)
    Method[] declaredMethods = clazz.getDeclaredMethods();
    for(Method m : declaredMethods){
      System.out.println(m);
    }
  }
  
  @Test
  public void test2() {
    Class clazz = Person.class;
    Method[] declaredMethods = clazz.getDeclaredMethods();
    for (Method m : declaredMethods) {
//1.获取方法声明的注解
      Annotation[] annos = m.getAnnotations();
      for (Annotation a : annos) {
        System.out.println(a + "KKKK");
      }
//2.权限修饰符
      System.out.print(Modifier.toString(m.getModifiers()) + "\t");
//3.返回值类型
      System.out.print(m.getReturnType().getName() + "\t");
//4.方法名
      System.out.print(m.getName());
      System.out.print("(");
//5.形参列表
      Class[] pTs = m.getParameterTypes();
      if(!(pTs == null && pTs.length == 0)){
        for(int i = 0;i < pTs.length;i++){
          if(i == pTs.length - 1){
            System.out.print(pTs[i].getName() + " args_" + i);
            break;
          }
          System.out.print(pTs[i].getName() + " args_" + i + ",");
        }
      }
      System.out.print(")");
//6.抛出的异常
      Class[] eTs = m.getExceptionTypes();
      if(eTs.length > 0){
        System.out.print("throws ");
        for(int i = 0;i < eTs.length;i++){
          if(i == eTs.length - 1){
            System.out.print(eTs[i].getName());
            break;
          }
          System.out.print(eTs[i].getName() + ",");
        }
      }
      System.out.println("TQA");
    }
  }
}

四、获取运行时类的构造器结构

package github3;
import github2.Person;
import org.junit.Test;
import java.lang.reflect.Constructor;
public class OtherTest {
  @Test
  public void test(){
    Class clazz = Person.class;
//getConstructors():获取当前运行时类中声明为public的构造器
    Constructor[] constructors = clazz.getConstructors();
    for(Constructor c : constructors){
      System.out.println(c);
    }
//getDeclaredConstructors():获取当前运行时类中声明的所有的构造器
    Constructor[] declaredConstructors = clazz.getDeclaredConstructors();
    for(Constructor c : declaredConstructors){
      System.out.println(c);
    }
  }
}

五、获取运行时类的父类及父类的泛型

package github3;
import github2.Person;
import org.junit.Test;
import java.lang.reflect.Constructor;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

public class OtherTest {
//获取运行时类的父类
  @Test
  public void test2(){
    Class clazz = Person.class;
    Class superclass = clazz.getSuperclass();
    System.out.println(superclass);
  }
//获取运行时类的带泛型的父类
  @Test
  public void test3(){
    Class clazz = Person.class;
    Type genericSuperclass = clazz.getGenericSuperclass();
    System.out.println(genericSuperclass);
  }
//获取运行时类的带泛型的父类的泛型
  @Test
  public void test4(){
    Class clazz = Person.class;
    Type genericSuperclass = clazz.getGenericSuperclass();
    ParameterizedType paramType = (ParameterizedType) genericSuperclass;
//获取泛型类型
    Type[] actualTypeArguments = paramType.getActualTypeArguments();
//    System.out.println(actualTypeArguments[0].getTypeName());
    System.out.println(((Class)actualTypeArguments[0]).getName());
  }
}

六、获取运行时类的接口、所在包、注解等

package github3;
import github2.Person;
import org.junit.Test;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
public class OtherTest {
//获取运行时类实现的接口
  @Test
  public void test5(){
    Class clazz = Person.class;
    Class[] interfaces = clazz.getInterfaces();
    for(Class c : interfaces){
      System.out.println(c);
    }
//获取运行时类的父类实现的接口
    Class[] interfaces1 = clazz.getSuperclass().getInterfaces();
    for(Class c : interfaces1){
      System.out.println(c);
    }
  }
//获取运行时类所在的包
  @Test
  public void test6(){
    Class clazz = Person.class;
    Package pack = clazz.getPackage();
    System.out.println(pack);
  }
//获取运行时类声明的注解
  @Test
  public void test7(){
    Class clazz = Person.class;
    Annotation[] annotations = clazz.getAnnotations();
    for(Annotation annos : annotations){
      System.out.println(annos);
    }
  }
}