• 【注解和反射】获取类运行时结构


    继上一篇博客【注解和反射】类加载器-CSDN博客

    目录

    七、获取类运行时结构

    测试

    getFields()和getDeclaredFields()

    getMethods()和getDeclaredMethods()


    七、获取类运行时结构

    获取类运行时结构通常指的是在Java等面向对象编程语言中,使用反射(Reflection)机制来检查类、接口、字段(Field)和方法(Method)等程序元素的能力。这种能力允许你在运行时动态地获取类的信息,并且可以调用类的方法、改变字段的值等。

    在Java中,获取类运行时结构主要包括以下几个方面:

    1. 获取Class对象: 要获取类的运行时结构,首先需要获取代表该类的Class对象。这可以通过多种方式实现,例如使用.class语法、Class.forName()方法或通过对象的getClass()方法。

    2. 获取类的名称: 通过Class对象的getName()方法可以获取类的全限定名(包括包名)。

    3. 获取类的修饰符: 使用getModifiers()方法可以获取类的修饰符(如publicabstractfinal等),通常与Modifier.toString()方法结合使用以获取可读的修饰符字符串。

    4. 获取类的父类和实现的接口: 通过getSuperclass()方法可以获取类的直接父类,而getInterfaces()方法则返回当前类实现的接口数组。

    5. 获取类的字段: 使用getDeclaredFields()方法可以获取类中声明的所有字段,无论访问权限如何。而getFields()方法仅返回public字段。

    6. 获取类的方法: 类似地,getDeclaredMethods()方法返回类中声明的所有方法,而getMethods()方法仅返回public方法,包括继承自父类的方法。

    7. 获取类的构造器: 通过getDeclaredConstructors()方法可以获取类的所有构造器,而getConstructors()方法仅返回public构造器。

    8. 获取类的注解: 如果类、方法、字段等上面有注解(Annotation),可以使用getAnnotations()getDeclaredAnnotation()等方法来获取这些注解信息。

    9. 获取类的内部类和接口: 通过getDeclaredClasses()方法可以获取当前类中声明的所有内部类和接口。

    10. 判断类的特性Class类提供了一系列的方法来判断类的特性,如isInterface()isEnum()isAnnotation()isAnonymousClass()isArray()isPrimitive()等。

    获取类运行时结构的能力在Java中非常强大,它允许开发者在程序运行时动态地分析和操作类,这在很多场景下都很有用,比如框架设计、单元测试、序列化和反序列化、依赖注入等。然而,使用反射也需要谨慎,因为它可能会破坏封装性,降低性能,并且使代码更加复杂和难以维护。

    测试

    首先,我们需要定义一个 User 类,

    1. class User{
    2. private String name;
    3. private int id;
    4. private int age;
    5. public User(String name, int id, int age) {
    6. this.name = name;
    7. this.id = id;
    8. this.age = age;
    9. }
    10. public User() {
    11. }
    12. public String getName() {
    13. return name;
    14. }
    15. public void setName(String name) {
    16. this.name = name;
    17. }
    18. public int getId() {
    19. return id;
    20. }
    21. public void setId(int id) {
    22. this.id = id;
    23. }
    24. public int getAge() {
    25. return age;
    26. }
    27. public void setAge(int age) {
    28. this.age = age;
    29. }
    30. @Override
    31. public String toString() {
    32. return "User{" +
    33. "name='" + name + '\'' +
    34. ", id=" + id +
    35. ", age=" + age +
    36. '}';
    37. }
    38. }

    在代码示例中,Test05 类有一个 main 方法,该方法执行了以下操作:

    1. 创建了一个 User 类的对象 user
    2. 通过调用 user.getClass() 获取了 User 类的 Class 对象,并将其存储在变量 c1 中。
    3. 打印了 c1 所代表的类的全名(包名 + 类名)和简单类名(仅类名)。
    4. 打印了一行分隔符 -------
    5. 获取了 c1 所代表的类声明的所有字段(不包括继承的字段),并遍历打印了每个字段的信息。
    1. public class Test05 {
    2. public static void main(String[] args) throws ClassNotFoundException {
    3. User user = new User();
    4. Class c1 = user.getClass();
    5. System.out.println(c1.getName());
    6. System.out.println(c1.getSimpleName());
    7. System.out.println("-------");
    8. // Field[] fields = c1.getFields();
    9. Field[] fields = c1.getDeclaredFields();
    10. for(Field f: fields){
    11. System.out.println(f);
    12. }
    13. }
    14. }

    这里是输出结果的详细分析:

    1. System.out.println(c1.getName()); 打印了User类的完全限定名,即包括包名(如果有的话)和类名。因为User类没有指定包名,所以输出就是User

    2. System.out.println(c1.getSimpleName()); 打印了User类的简单名字,也就是不包括包名的类名,所以输出还是User

    3. 在打印了一行分隔符之后,代码通过c1.getDeclaredFields()获取了User类中声明的所有字段,包括privateprotected、默认(包私有)和public字段。在这个例子中,User类有三个private字段:nameidage。这些字段被打印出来,包括它们的访问修饰符、类型、类名和字段名。

    getFields()和getDeclaredFields()

    在Java的反射API中,getFields()getDeclaredFields()方法都用于获取类的字段,但它们在获取字段的范围和访问权限上有明显的区别:

    1. getFields():

      • 这个方法返回的是当前类及其所有父类(包括Object类)中声明的public字段
      • 它不包括当前类中声明的privateprotected和默认(包私有)访问级别的字段。
      • 如果当前类或其父类中没有public字段,那么这个方法将返回一个长度为0的数组。
    2. getDeclaredFields():

      • 这个方法返回的是当前类中声明的所有字段,无论它们的访问权限是什么(publicprivateprotected或默认)。
      • 它不包括父类中声明的任何字段,只查看当前类的字段。
      • 即使当前类中没有字段,这个方法也会返回一个数组,只不过数组的长度是0。

    通常,如果你只对当前类的字段感兴趣,而不关心父类的字段,那么你应该使用getDeclaredFields()。同时,如果你需要访问非public字段,你也需要使用getDeclaredFields(),因为getFields()不会返回这些字段。

    另外,值得注意的是,如果你使用getDeclaredFields()获取了非public字段,并且想要访问或修改这些字段的值,你需要先调用Field.setAccessible(true)来允许访问这些字段,否则会抛出IllegalAccessException异常。

    getMethods()getDeclaredMethods()

    现在,让我们来讨论getMethods()getDeclaredMethods()的区别:

    1. getMethods():

      • 这个方法返回当前类及其所有父类(包括Object类)中声明的所有public方法。
      • 它不包括当前类中声明的privateprotected和默认(包私有)访问级别的方法。
      • 返回的数组包含了从当前类开始,沿着继承链向上直到Object类的所有public方法。
    2. getDeclaredMethods():

      • 这个方法返回当前类中声明的所有方法,无论它们的访问权限是什么(publicprivateprotected或默认)。
      • 它不包括父类中声明的任何方法,只查看当前类的方法。
      • 即使当前类中没有方法,这个方法也会返回一个数组,只不过数组的长度是0。

    与字段的情况类似,如果你只对当前类的方法感兴趣,而不关心父类的方法,那么你应该使用getDeclaredMethods()。同时,如果你需要访问非public方法,你也需要使用getDeclaredMethods(),因为getMethods()不会返回这些方法。

    同样值得注意的是,如果你使用getDeclaredMethods()获取了非public方法,并且想要调用这些方法,你需要先调用Method.setAccessible(true)来允许访问这些方法,否则会抛出IllegalAccessException异常。

  • 相关阅读:
    python自动解析301、302重定向链接
    【兔子王赠书第3期】《案例学Python(进阶篇)》
    MySQL 练习<2>
    数据结构--堆
    Appium自动化测试:通过appium的inspector功能无法启动app的原因
    「地埋式积水监测站」智慧防汛,科技先行
    数据结构与算法之Hash&BitMap
    pytorch 入门(一)
    ArduPilot开源飞控之AP_AHRS
    软件设计原则 1小时系列 (C++版)
  • 原文地址:https://blog.csdn.net/qq_45956730/article/details/138172865