尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Java反射和注解
一 . 反射1. 反射概念反射程序运行时动态获取类的字节码信息 (Class 对象)并且操作构造器、成员变量、成员方法。正常编码编译期就知道类反射运行时才拿到类动态创建对象、操作成员变量事先代码里不用写死new Student()/new Teacher()。入口Class对象字节码对象2 .1 反射第一步:获取 Class 对象反射第一步拿到 Class 对象第二步通过 Class 对象获取构造器、方法或者字段对象第三步如果是私有成员打开访问权限第四步执行实例化、调用或者读写获取 Class 对象 3 种方式方式 1类名.class【静态方式推荐不触发类加载】Class c1 User.class;不需要创建对象直接通过类的字面量获取 Class。方式 2对象.getClass()【已经有实例对象时使用】User u new User();Class? c2 u.getClass();方式 3Class.forName(全类名)【最常用框架底层用的最多】Class? c3 Class.forName(“com.User”);传入完整包名 类名字符串会触发类加载加载、链接、初始化。JDBC 加载驱动、Spring Bean 扫描底层就是这个写法。2 . 2 反射第二步从 Class 对象获取「构造器 / 方法 / 成员变量」1. 从class类中获取构造器Constructor用来创建对象getConstructor(参数类型...)获取public 公开的构造器getDeclaredConstructor(参数类型...)获取任意权限(public/private)构造器常用getConstructors()获取所有 public 构造器数组getDeclaredConstructors()获取全部构造器数组3.setAccessible(true)暴力访问私有构造4.调用newInstance()创建对象//获取到这个类的class对象CatcCat.class;// 1. 获取【本类任意权限包括私有】的有参构造器对象第二步Constructorconstructor1c.getDeclaredConstructor(String.class,Int.class);// 2. 获取构造器名字 参数个数并打印System.out.println(constructor1.getName()--constructor1.getParameterCount());//得到全类名和参数个数2// 3. 暴力反射关闭访问权限检查第三步constructor1.setAccessible(true);// 禁止检查访问权限// 4. 通过构造器实例化对象第四步Catcat(Cat)constructor1.newInstance(参数1,参数2);// 5. 打印对象System.out.println(cat);核心:利用反射机制调用类的构造器来创建对象。反射拿到 Constructor构造方法对象主要作用是在运行时动态创建类的实例还可以读取构造器信息甚至调用私有构造创建对象。问 :setAccessible(true)是修改类中构造器的权限为 public 吗不是只是临时关闭访问权限检查并没有修改源码里 private 修饰符。只对当前这个 constructor 对象生效。2.从 Class 对象获取成员变量class中获取成员变量Field的四个方法Field[] getFields()获取所有 public成员变量包括父类的 public 字段Field[] getDeclaredFields()获取本类中全部成员变量private、protected、public、default 都拿到不包含父类的字段Field getField(String name)根据名字获取单个 public成员变量可找父类 publicField getDeclaredField(String name)根据名字获取本类中任意权限的单个成员变量private 也能拿到不找父类Field成员变量对象的作用反射拿到Field 对象就是把类的成员变量封装成一个对象在程序运行阶段动态读取 / 修改 一个对象的成员变量的值哪怕这个变量是private私有的。核心能力读取成员变量的值field.get(对象)传入对象拿到这个对象该成员变量的值修改成员变量的值field.set(对象, 新值)接上图Cat cat new Cat ;fName.set(cat,“加菲猫”)给对象的成员变量动态赋值突破访问权限限制field.setAccessible(true)开启暴力反射原本private私有变量也能读写只是关闭权限检查没有修改源码访问修饰符3.从 Class 对象获取成员方法核心作用:在程序运行阶段动态调用这个成员方法。getMethods()能拿到父类 publicgetDeclaredMethods()只能拿本类public/private/protected 都拿到父类方法拿不到。Method getMethod(String name,参数类型...)根据方法名 参数类型获取单个 public 方法可找父类 publicMethod getDeclaredMethod(String name,参数类型...)根据方法名 参数类型获取本类任意权限单个方法private 方法也可以不找父类调用:public Object invoke(Object obj, Object... args)执行方法的核心反射获取 Method 对象的目的。public void setAccessible(boolean flag)设置为 true禁止检查访问控制暴力反射获取 Class获取对应的 Constructor/Method/FieldClass 拿信息Constructor 造对象Field 读写变量Method 调用方法。私有成员setAccessible(true)开启暴力反射,关闭访问权限检查访问 private 成员不是修改权限执行对应的操作二. 反射的作用和应用场景反射Reflection正常编码编译期就知道Student s new Student()写死类名。反射运行时才拿到类动态创建对象、操作成员变量事先代码里不用写死new Student()/new Teacher()。1.反射核心作用运行时获取类的全部信息获取类名、成员变量 (Field)、构造器 (Constructor)、方法 (Method)包括private私有成员。动态创建对象运行时通过 Class 对象调用构造方法实例化对象不用编译期 new。动态读写成员变量的值即使属性是privatesetAccessible(true)可以绕过访问检查读取 / 修改对象属性。动态调用对象的方法运行时找到 Method执行方法不需要编译期写死调用。核心特点动态。编译期不知道要操作哪个类运行时才确定。✅优点灵活性强动态编程解耦框架底层实现基础。❌缺点性能较差破坏封装可以访问私有成员代码复杂异常在运行时才暴露。用反射做一个简易框架,对于任何一个对象,都可以将对象的字段和对应的值保存到文件中去2. 反射的应用场景面试重点① 框架底层最主要场景上面代码Framework就是简易框架思想SpringIOC 容器根据配置文件 / 注解通过反射创建对象注入属性MyBatis读取 xml 映射文件反射实例化实体类给对象字段赋值封装数据库查询结果框架不知道你将来会写什么实体类Student/Teacher只能靠反射动态操作。② 序列化 / 反序列化对象和文本、JSON 互转JSON 工具Jackson、FastJSON把对象转 JSON 字符串 / JSON 转对象底层都是反射扫描属性读写值。例如把对象所有字段保存到 data.txt就是简易序列化。③ 配置文件解析配置文件写类名程序读取配置反射加载类创建对象。例如data.txt写com.Student程序读到字符串用 Class.forName 加载这个类。④ 注解解析注解 反射配套使用自定义注解运行时通过反射判断类 / 字段上有没有注解做逻辑控制。例加注解NotSave框架反射扫描到这个注解就跳过该字段不保存到文件。⑤ 单元测试框架 JUnitJUnit 识别Test注解运行时通过反射找到标记的方法自动执行测试方法。三 . 注解1. 定义注解AnnotationJava 里一种标记写在类、方法、成员变量上面给程序附加额外信息。注解本身不会直接执行代码需要反射在运行时读取注解然后根据注解做对应的逻辑。2. 作用给编译器提示信息例如Override检测方法是否重写父类方法Deprecated标记方法过时。编译期生成代码比如 Lombok 的Data。运行时框架通过反射读取注解实现功能和刚才的 Framework 配套SpringComponent、AutowiredJUnitTest我们可以自定义注解标记某个字段不要保存到 txt 文件。3.自定义注解含义用interface声明搭配元注解Target指定使用位置(类、方法、成员变量 FIELD )Retention指定生命周期可以定义注解属性)。 如果需要运行时反射读取Retention 必须设置为RetentionPolicy.RUNTIME。Target指定使用位置(元注解的)-TYPE类、接口-FIELD成员变量字段-METHOD成员方法-PARAMETER方法参数-CONSTRUCTOR构造器-LOCAL_VARIABLE局部变量- 多个:Target({ElementType.FIELD,ElementType.METHOD})Retention指定注解保留到哪个阶段(元注解的)-RetentionPolicy.SOURCE源码阶段编译后丢弃-RetentionPolicy.CLASS保留到 class 字节码运行时丢失默认-RetentionPolicy.RUNTIME运行时保留可以通过反射读取框架必用3. 可以在注解内部定义属性。//元注解:描述注解的注解Target(ElementType.FIELD)//注解只能写在成员变量上Retention(RetentionPolicy.RUNTIME)//运行时保留反射才能读到publicinterfaceNotSave{//标记加上这个注解的字段不要保存到data.txt}使用:publicclassTeacher{privateStringname;NotSave//这个age字段不会写入txtprivateIntegerage;privateDoublesalary;}然后在Framework的 saveObject 里用反射判断字段上有没有NotSave有就跳过不输出。重点想用反射解析注解Retention 必须写 RUNTIME模拟Junit框架需求:定义若干个方法,只要加了注解AnnotationTest01,就会触发该方法执行(分析:1.定义一个自定义注解,只能注解方法,存活范围一直都在 2.部分方法不加自定义注解)四 . 什么是注解解析注解解析通过反射或者 APT 技术读取类、方法、属性上标记的注解信息根据注解中定义的参数执行对应的逻辑前提自定义注解必须加Retention (RetentionPolicy.RUNTIME)1. 基础前提最重要必背元注解Retention必须设置为RetentionPolicy.RUNTIME只有 RUNTIME注解保留到运行期JVM 加载字节码后反射才能读到注解如果是CLASS/SOURCE运行时拿不到注解解析失效Target限定注解能标注在什么位置类、字段、方法等所有能放注解的元素Class、Field、Method、Constructor都实现全部实现了AnnotatedElement接口这个接口提供注解解析方法2. AnnotatedElement 三大核心方法boolean isAnnotationPresent(注解.class)判断是否存在该注解返回 true/false ✅最常用判断有没有标记比如判断字段上有没有NotSavegetDeclaredAnnotation(注解.class)获取指定类型注解对象没有返回 null 获取注解读取注解里面的属性值Annotation[] getDeclaredAnnotations()获取当前元素上所有注解返回注解数组 遍历全部注解3. 注解解析核心思想要解析谁上面的注解就先拿到谁的对象。解析类上注解 → 获取Class对象解析成员变量注解 → 获取Field对象解析方法注解 → 获取Method对象解析构造器注解 → 获取Constructor对象Class、Field、Method、Constructor都实现了AnnotatedElement接口所以全都拥有解析注解的方法。黑马反射学习链接
RELATED

相关推荐

软考架构设计师论文 —— 论AI驱动的智能运维架构及其应用(3)

软考架构设计师论文 —— 论AI驱动的智能运维架构及其应用(3)

接前一篇文章:软考架构设计师论文 —— 论AI驱动的智能运维架构及其应用(2) 论题 随着软件系统规模的不断扩大和云计算、微服务架构的普及,运维工作正面临着复杂度高、变化快、实时性要求强等挑战。传统的人工运维方式往往存在效率低、响应慢、容易出错等问题,而DevOps的…

📅 2026/9/30 2:36:38
KingbaseES KSQL Developer 的连接管理、数据处理与对象管理

KingbaseES KSQL Developer 的连接管理、数据处理与对象管理

写在前面 先说说我遇到的情况。手头要维护的数据库不止一种,KingbaseES、MySQL、Oracle 都有。每换一种库就要打开对应的客户端,连接参数记了一堆,还老填错。用命令行倒是到哪都统一,可语法记不住、敲错了排查半天,效率…

📅 2026/9/30 2:36:38
亲测jev模型,认为可以火了

亲测jev模型,认为可以火了

typesafe.ai推出了 jev 离散决策模型,说人话就是“只做选择题,不做问答题”,你问一个问题,他只判断/选择,响应严格的JSON格式给程序使用。官网比喻是一个智能if语句,快到就像访问普通API接口一样&#xff0…

📅 2026/9/30 2:36:38
MORE NEWS

更多资讯

📰

漫无目的刷算法题:从简单题开始,反而成长更快

看到这个标题的时候我乐了。这不就是我的日常吗——晚上九点半洗完澡坐电脑前,本来只想看一眼明天的天气,结果鬼使神差打开算法题库,随手点开一道“简单”,就开始刷了。没有计划表,没有目标清单,纯粹是想动…

📰

Linux服务器自建Git仓库:多开发者SSH协同实战指南

很多技术团队聊到"多开发者协同",第一反应就是开个GitHub组织、或者上GitLab托管,但真到落地的时候你会发现,"托管平台能用"和"服务器上自主可控"完全是两码事。我这些年帮不同类型的小团队搭过Git协同环境&am…

📰

亿申能源换热器产品可靠性如何,通过哪些行业认证

江苏亿申能源装备有限公司是扎根江苏靖江的实体承压装备制造企业, 手机:19825589000 核心业务聚焦储罐、换热器、反应釜等非标承压装备的设计、制造与安装,致力于为多行业客户提供合规可靠的一站式承压装备解决方案。 核心实力拆解 技术研发…

📰

魔力宝贝秒遇怪原理与实操:游戏遇敌机制深度解析

1. 这不是外挂,是游戏机制的“时间折叠术”“魔力宝贝秒遇怪”这五个字,在老玩家社群里一抛出来,就像往沸水里滴进一滴油——瞬间炸开。它不等于“自动打怪”,也不等于“跳过战斗”,更不是什么神秘的第三方工具。它本质…

📰

SpringBoot+Vue+MyBatis+MySQL:短流量数据分析与可视化系统全栈实战

做企业级流量分析系统这几年,我接手过不少类似的项目,但真正从零把一套“短流量数据分析与可视化管理系统”完整落地——从前端界面到后端接口、从数据库设计到部署上线——的经历,对我个人来说帮助特别大。这个项目用到的整套方案是 SpringB…

📰

RabbitMQ延迟队列核心原理与生产实践

之前有个做交易系统的朋友问我:用户下单 15 分钟内没支付就要自动关单,还要顺带释放库存,这个东西怎么设计最靠谱。他第一反应是写个定时任务每 30 秒扫一次订单表,结果数据量一上来,扫描成本直线上升,真正…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬