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

继上一篇博客【注解和反射】类加载器-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 类,

class User{private String name;private int id;private int age;public User(String name, int id, int age) {this.name = name;this.id = id;this.age = age;}public User() {}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getId() {return id;}public void setId(int id) {this.id = id;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "User{" +"name='" + name + '\'' +", id=" + id +", age=" + age +'}';}
}

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

  1. 创建了一个 User 类的对象 user
  2. 通过调用 user.getClass() 获取了 User 类的 Class 对象,并将其存储在变量 c1 中。
  3. 打印了 c1 所代表的类的全名(包名 + 类名)和简单类名(仅类名)。
  4. 打印了一行分隔符 -------
  5. 获取了 c1 所代表的类声明的所有字段(不包括继承的字段),并遍历打印了每个字段的信息。

public class Test05 {public static void main(String[] args) throws ClassNotFoundException {User user = new User();Class c1 = user.getClass();System.out.println(c1.getName());System.out.println(c1.getSimpleName());System.out.println("-------");// Field[] fields = c1.getFields();Field[] fields = c1.getDeclaredFields();for(Field f: fields){System.out.println(f);}}
}

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

  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异常。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/4365.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

迁移学习基础知识

简介 使用迁移学习的优势: 1、能够快速的训练出一个理想的结果 2、当数据集较小时也能训练出理想的效果。 注意:在使用别人预训练的参数模型时,要注意别人的预处理方式。 原理: 对于浅层的网络结构,他们学习到的…

leetcode_29.两数相除

29. 两数相除 题目描述:给你两个整数,被除数 dividend 和除数 divisor。将两数相除,要求 不使用 乘法、除法和取余运算。 整数除法应该向零截断,也就是截去(truncate)其小数部分。例如,8.345 将…

[Swift]单元测试

编写单元测试是确保你的代码质量和功能正确性的重要步骤 一、编写单元测试的详细流程 1. 创建一个新的Xcode项目 如果你尚未创建一个项目,首先你需要在Xcode中创建一个新的iOS项目: 打开Xcode,选择“File” > “New” > “Project”…

window驱动开发-内核线程

在内核开发中,不可避免需要用到多线程技术,毕竟驱动是针对所有进程,而非某个特定进程,故驱动自然也是多线程的。在设计目标中,已经明确了驱动例程设计中,需要考虑的问题之一就是"重入"的概念&…

重生之我是Nginx服务专家

nginx服务访问页面白色 问题描述 访问一个域名服务返回页面空白,非响应404。报错如下图。 排查问题 域名解析正常,网络通讯正常,绕过解析地址访问源站IP地址端口访问正常,nginx无异常报错。 在打开文件时,发现无法…

R可视化:ggplot2绘制双y轴图

介绍 ggplot2绘制双y轴图加载R包 knitr::opts_chunk$set(message = FALSE, warning = FALSE) library(tidyverse) library(readxl)# rm(list = ls()) options(stringsAsFactors = F) options(future.globals.maxSize = 10000 * 1024^2)Importing data 下载Underdetection of c…

IDEA实现Springboot项目自动热部署

每当我们在修改代码时,往往需要重新启动项目,这样不仅浪费时间而且很麻烦,我们可以通过IDEA的热部署来提高效率 1、首先点file >> settings >> Build Excution >> Compire,选择Build project auto matically 2.…

CMakeLists.txt中如何添加编译选项?

1. 引子 编译器有多种可供选择,如g、c、clang等,如下以c作为示例。 2. 使用CMAKE_CXX_FLAGS添加编译选项 在Makefile中可能用类似如下的指令来添加编译选项: /usr/bin/c -Wall -Wextra -Wno-sign-compare -Wno-unused-variable -Wno-unuse…

flutter笔记-主要控件及布局

文章目录 1. 富文本实例2. Image2.1 本地图片2.2 网络图片 笔记3. 布局4. 滑动相关view4.1 GridView类似九宫格view4.2 ListView 关于widget的生命周期的相关知识这里就不做介绍,和很多语言类似; 1. 富文本实例 Dart中使用richtext,示例如下…

int和byte数组相互转换详解

转换之前我们需要了解各种进制之间的关系,不太了解的可以先看下计算机组成原理和体系 这篇文章 byte byte是字节的意思,一个字节等于8位,范围是 0000 0000 ~ 1111 1111(十六进制:0x0~0xff),总共包含256个数。 有符号的byte表示的…

java 和 php 的AES 128位 256位 加解密 【java解密php的AES加密方案】

项目需要 需要java可以解密 php加密的 字符串 , 使用的方法是 AES128位加解密 坑一踩完 ,还是直接上代码 package com.xxx.init.utils;import com.xxx.init.utils.BaseDataUtil; import com.xxx.init.exception.xxxRuntimeException; import com.xxx.i…

ARCGIS PRO SDK POINT层唯一值渲染按角度旋转

c 代码: 按Direction字段旋转&#xff0c;旋转样式为数学 protected override async void OnClick(){var featLayer MapView.Active.Map.GetLayersAsFlattenedList().OfType<FeatureLayer>().First();await QueuedTask.Run(() >{var render featLayer.GetRenderer()…

Python异步编程详解:asyncio和多线程

Python 的异步编程是一种通过协程、事件循环和异步I/O操作来实现并发的技术。在 Python 中&#xff0c;asyncio 是用于编写单线程并发代码的库&#xff0c;而多线程则涉及使用 Python 的 threading 模块。下面我们将详细探讨这两种技术的使用和它们的适用场景。 ### 1. asynci…

6 Zookeeper 配置说明

Zookeeper 的三种工作模式 单机模式:存在单点故障。集群模式:在多台机器上部署 Zookeeper 集群,适合线上环境使用。伪集群模式:在一台机器同时运行多个 Zookeeper 实例,仍然有单点故障问题,当然其中配置的端口号要错开的,适合实验环境模拟集群使用。Zookeeper 的三种端口…

C 练习实例36 - 求100之内的素数

C 练习实例36 - 求100之内的素数 题目&#xff1a; 求100之内的素数。 程序分析&#xff1a; 质数&#xff08;prime number&#xff09;又称素数&#xff0c;有无限个。一个大于1的自然数&#xff0c;除了1和它本身外&#xff0c;不能被其他自然数整除。 程序源代码&#x…

Vue3+Vite开发的项目进行加密打包

本文主要介绍Vue3+Vite开发的项目如何进行加密打包。 目录 一、vite简介二、混淆工具三、使用方法1. 安装插件:2. 配置插件:3. 运行构建:4. 自定义混淆选项:5. 排除文件:下面是Vue 3+Vite开发的项目进行加密打包的方法。 一、vite简介 Vite 是一个由 Evan You 创造的现代…

XBoot:基于Spring Boot 2.x的一站式前后端分离快速开发平台

XBoot&#xff1a;基于Spring Boot 2.x的一站式前后端分离快速开发平台 摘要 随着信息技术的迅速发展&#xff0c;快速构建高质量、高可靠性的企业级应用成为了迫切需求。XBoot&#xff0c;作为一个基于Spring Boot 2.x的一站式前后端分离快速开发平台&#xff0c;通过整合微信…

python_AI库 matplotlib在AI程序中的应用介绍

本文默认读者具备以下技能&#xff1a; 熟悉Python基础知识&#xff0c;能自行阅读并理解代码含义 对AI有基础了解 基础高等数学知识 前文对matplotlib在日常生活的基础应用作了介绍&#xff0c;那么matplotlib与我们的AI又有什么联系呢&#xff1f; 在 AI 程序中&#xff0c…

针对icon报错

针对上篇文章生成图标链接中图标报错 C# winfrom应用程序添加图标-CSDN博客 问题&#xff1a;参数“picture”必须是可用作Icon的参数 原因&#xff1a;生成的ico图标类型不匹配 解决方法&#xff1a; 更改导出的ico类型

iOS - 多线程-读写安全

文章目录 iOS - 多线程-读写安全1. 多读单写1.1 场景1.2 实现方案1.2.1 pthread_rwlock&#xff1a;读写锁1.2.1.1 示例 1.2.2 dispatch_barrier_async&#xff1a;异步栅栏调用1.2.2.1 示例 iOS - 多线程-读写安全 假设有一个文件&#xff0c;A线程进行读取操作&#xff0c;B…