2023.12.12 关于 Java 反射详解
目录
基本概念
定义
用途
反射相关的类
反射基本原理
Class 类中的相关方法
常用获得类相关的方法
常用获得类中属性相关的方法
常用获得类中构造器相关的方法
常用获得类中方法相关的方法
实例理解
反射优缺点
基本概念
定义
- Java 的反射(reflection)机制是一种强大功能,它可以让我们在运行时动态地获取和操作 类 或 对象 的信息
 实例理解
- 我们可以通过反射机制来创建一个类的对象,而不需要使用 new 关键字
 - 我们也可以通过反射机制来访问或修改一个对象的私有属性或方法,而不需要遵循封装原则
 - 我们还可以通过反射机制来调用一个对象的任意方法,而不需要知道它的参数类型或返回值类型
 
用途
典型用途一:
- 在开发第三方应用时,我们可能会遇到一些类的成员变量、方法或属性是私有的,或者只对系统应用开放,这就意味着我们不能直接访问这些成员或方法
 - 这时我们便可以在运行时 通过 Java 的反射机制 来动态地访问和操作类的内部成员,包括私有成员和方法
 典型用途二:
- 反射在开发通用框架 Spring 中起着重要的作用
 - 在Spring 框架中,所有类(Bean)都由 Spring 容器进行管理,这些 Bean 可以通过 XML 配置或注解来配置
 - 当我们从容器中获取Bean 以进行依赖注入时,容器会读取配置信息,这些配置信息包含了类的信息,比如类的名称、属性、方法等
 - Spring根据这些信息 动态地创建这些类的实例,这个过程就是所谓的 依赖注入,该过程中,反射起到了关键作用
 - Spring 使用反射来动态地创建类的实例,调用方法,以及设置属性值
 
反射相关的类
反射基本原理
- Java 的反射机制是基于 java.lang.Class 类实现的
 - 当我们编译一个 Java 文件时,会生成一个 .class 文件
 - 当 JVM 加载这个 .class 文件时,会将其解析为一个 java.lang.Class 类的对象
 - 在程序运行时,每个 Java 文件都会被 JVM 解析为一个 Class 类的实例
 - 这个 Class 类的实例包含了该 Java 文件中所定义类的所有信息,包括类的名称、属性、方法等
 - 我们可以通过 Java 的反射机制来操作这个 Class 类的实例
 - 具体来说,我们可以使用反射来获取类的属性和方法,甚至可以添加或修改类的属性和方法
 - 这使得我们可以在运行时动态地操作类,使其成为一个 动态的类
 
类名 用途 Class 类 代表类的实体,在运行的 Java 应用程序中表示类和接口 Field 类 代表类的成员变量、类的属性 Method 类 代表类的方法 Constructor 类 代表类的构造方法 
Class 类中的相关方法
常用获得类相关的方法
方法 用途 getClassLoader() 获得类的加载器 getDeclaredClasses() 返回一个数组,数组中包含该类中所有类和接口类的对象(包括私有的) forName(String className) 根据类名返回类的对象 newInstance() 创建类的实例 getName() 获得类的完整路径名字 常用获得类中属性相关的方法
方法 用途 getField(String name) 获得某个公有的属性对象 getFields() 获得所有公有的属性对象 getDeclaredField(String name) 获得某个属性对象 getDeclaredFields() 获得所有属性对象 常用获得类中构造器相关的方法
方法 用途 getConstructor(Class <?> parameterTypes) 获得该类中与参数类型匹配的公有构造方法 getConstructors() 获得该类的所有公有构造方法 getDeclaredConstructor(Class <?> parameterTypes) 获得该类中与参数类型匹配的构造方法 getDeclaredConstructors() 获得该类所有构造方法 常用获得类中方法相关的方法
方法 用途 getMethod(String name, Class <?> parameterTypes) 获得该类某个公有的方法 getMethods() 获得该类所有公有的方法 getDeclaredMethod(String name, Class <?> parameterTypes) 获得该类某个方法 getDeclaredMethods() 获得该类所有方法 
实例理解
- 此处我们先创建一个 Student 类
 class Student{//私有属性nameprivate String name = "master";//公有属性agepublic int age = 18;//不带参数的构造方法public Student(){System.out.println("Student()");}private Student(String name,int age) {this.name = name;this.age = age;System.out.println("Student(String,name)");}private void eat(){System.out.println("make hamburger!");}public void sleep(){System.out.println("go to bed!");}private void function(String str) {System.out.println(str);}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';} }
- 此处介绍三种方式来获取 Student 的 Class 对象
 public class Demo1 {public static void main(String[] args) { // 有三种方式可以获取 Class 对象Student student1 = new Student(); // 1、通过对象的 getClass() 方法Class<?> c1 = student1.getClass(); // 2、通过类名 .class 获取Class<?> c2 = Student.class; // 3、通过调用 Class.forName() 方法获取了 Student 类的 Class 对象 // Class.forName() 方法需要一个类的全限定名(包括 包名和类名) 作为参数 // 此处的 ? 是一个通配符,用于表示未知类型 // 当我们声明一个泛型变量时,如果我们不确定或不关心实际的类型参数,我们可以使用 ? 来表示Class<?> c3 = null;try {c3 = Class.forName("Student");} catch (ClassNotFoundException e) {throw new RuntimeException(e);} // 此处证明通过上述三种方式所获取的 Class 对象 都是同一个System.out.println((c1.equals(c2) && c1.equals(c3) && c2.equals(c3)) ? "true" : "false");} }
- 此处我们通过反射机制创建一个对象
 import java.lang.reflect.InvocationTargetException;public class ReflectClassDemo {// 通过反射创建一个对象public static void reflectNewInstance() throws InstantiationException, IllegalAccessException, ClassNotFoundException {Class<?> c3 = Class.forName("Student"); // 通过调用 Class 类的 newInstance() 方法来创建一个 c3 对应类的新实例 // newInstance() 方法调用的是这个类的无参构造函数 // 如果这个类没有无参构造函数,或者无参构造函数是私有的,那么 newInstance 会抛出一个异常 // 因为 newInstance() 方法返回的类型为 Object 类 所以需要类型转换,此处转换为 Student 类Student student = (Student) c3.newInstance();System.out.println(student);}public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, NoSuchFieldException {reflectNewInstance();} }运行结果:
- 此处我们通过反射机制获取私有的构造方法
 import java.lang.reflect.Constructor;public class ReflectClassDemo {// 通过反射获取私有的构造方法public static void reflectPrivateConstructor() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {Class<?> c3 = Class.forName("Student");Constructor<?> constructor = c3.getDeclaredConstructor(String.class,int.class); // 注意只要是涉及到 private 都要使用 setAccessible(true) 来打开权限,此处的构造方法为私有的constructor.setAccessible(true); // 此处利用构造方法 修改年龄和性别Student student = (Student)constructor.newInstance("xiaolin",20);System.out.println(student);}public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, NoSuchFieldException {reflectPrivateConstructor();} }运行结果:
- 此处我们通过反射机制获取私有属性
 import java.lang.reflect.Field;public class ReflectClassDemo {// 通过反射获取私有属性public static void reflectPrivateField() throws ClassNotFoundException, NoSuchFieldException, InstantiationException, IllegalAccessException {Class<?> c3 = Class.forName("Student");Field field = c3.getDeclaredField("name"); // 注意只要是涉及到 private 都要使用 setAccessible(true) 来打开权限,此处的 name 属性是私有的field.setAccessible(true);Student student = (Student) c3.newInstance(); // 此处修改私有属性field.set(student,"haoran");System.out.println(student);}public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, NoSuchFieldException {reflectPrivateField();} }运行结果:
- 此处我们通过反射机制获取私有方法
 import java.lang.reflect.Method;public class ReflectClassDemo {// 通过反射获取私有方法public static void reflectPrivateMethod() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {Class<?> c3 = Class.forName("Student");Method method1 = c3.getDeclaredMethod("function", String.class);Method method2 = c3.getDeclaredMethod("sleep"); // 注意只要是涉及到 private 都要使用 setAccessible(true) 来打开权限,此处的 function 方法是私有的method1.setAccessible(true);Student student = (Student) c3.newInstance(); // 此处给 function 方法传参method1.invoke(student,"此处利用反射机制给 function 方法传个字符串参数"); // 此处调用 sleep 方法,该方法为 public 无需额外打开权限,直接调用即可method2.invoke(student);}public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, NoSuchFieldException {reflectPrivateMethod();} }运行结果:
反射优缺点
优点
- 对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个类都能调用它的任意一个方法
 - 增加程序的灵活性和扩展性,降低耦合性,提高自适应性
 - 反射已经运用在很多流行框架,典型代表为 Spring
 缺点
- 使用反射会有效率问题,会导致程序效率降低
 - 反射技术绕过了源代码的技术,因而会带来维护问题
 - 反射代码比相应的直接代码更复杂
 
总结:
- 虽然反射非常强大,但也需要谨慎使用
 - 我们需要在反射带来的灵活性和可扩展性与其带来的性能开销、维护问题和代码复杂性之间找到一个平衡
 - 某些情况下,比如开发通用的框架,使用反射式非常有价值的
 - 但在其他情况下,我们可能更倾向于使用更简单、更直接的代码
 
相关文章:
2023.12.12 关于 Java 反射详解
目录 基本概念 定义 用途 反射相关的类 反射基本原理 Class 类中的相关方法 常用获得类相关的方法 常用获得类中属性相关的方法 常用获得类中构造器相关的方法 常用获得类中方法相关的方法 实例理解 反射优缺点 基本概念 定义 Java 的反射(reflection&a…...
【Qt QML入门】Image
Image类型显示一个图像。 使用source属性将图像的源指定为URL。图像可以以Qt支持的任何标准图像格式提供,包括位图格式,如PNG和JPEG,以及矢量图形格式,如SVG。 如果没有指定宽度和高度属性,图像将自动使用加载图像的大…...
Spark编程入门
1.8 Spark编程入门 1.8.1 通过IDEA创建Spark工程 ps:工程创建之前步骤省略,在scala中已经讲解,直接默认是创建好工程的 导入Pom文件依赖 <!-- 声明公有的属性 --><properties><maven.compiler.source>1.8</maven.compiler.source><maven.compiler…...
JVM 内存分析工具 Memory Analyzer Tool(MAT)的深度讲解
目录 一. 前言 二. MAT 使用场景及主要解决问题 三. MAT 基础概念 3.1. Heap Dump 3.2. Shallow Heap 3.3. Retained Set 3.4. Retained Heap 3.5. Dominator Tree 3.6. OQL 3.7. references 四. MAT 功能概述 4.1. 内存分布 4.2. 对象间依赖 4.3. 对象状态 4.4…...
浅谈 USB Bulk 深入浅出 (3) - USB Bulk 装置传输的注意事项
来源:大大通 作者:冷氣團 1 USB Bulk 是什么 USB 是即插即用使用差动信号的装置界面,是以 端点 ( Endpoint ),做为传输装置的输出入端,透过不同的端点 ( Endpoint ) 和模式,来进行与装置的沟通ÿ…...
c语言结构体调用格式与对齐
1.声明形式: struct 结构体名字 { 结构体成员 }结构体变量名; 2.赋值方法 3.结构体对齐: 1.起始偏移量:默认结构体第一个元素对齐0起始偏移量,第一个元素占一个字节,此时偏移量为1. 2.标准数ÿ…...
服务器常用命令介绍和负载监控的工具插件推荐
先赞后看,养成习惯!!!❤️ ❤️ ❤️ 码字不易,如果喜欢可以关注我哦! 如果本篇文章对你有所启发,欢迎访问我的个人博客 命令 服务器相关 5个常用命令 top Top命令不仅显示了当前内核服务的…...
linux 防火墙systemctl (个人笔记)
查看 systemctl status firewalld 开启 systemctl start firewalld 关闭 systemctl stop firewalld.service 查看所有 firewall-cmd --zonepublic --list-ports 开放端口:// --permanent 永久生效,没有此参数重启后失效 firewall-cmd --zonepublic --add-port9527/…...
处理器中store指令的处理
对于向存储器中保存数据的store指令来说,它在顺利离开流水线之前是不允许改变处理器状态的,只有等到它退休(retire)的时候,才允许将它携带的数据写到D-Cache中在此之前,store指令即使计算完毕,也会将结果暂存在一个缓存中…...
杨辉三角形-第11届蓝桥杯选拔赛Python真题精选
[导读]:超平老师的Scratch蓝桥杯真题解读系列在推出之后,受到了广大老师和家长的好评,非常感谢各位的认可和厚爱。作为回馈,超平老师计划推出《Python蓝桥杯真题解析100讲》,这是解读系列的第17讲。 杨辉三角形&#…...
我们一起做过的SPA——Nuxt.js介绍
Nuxt.js 1 我们一起做过的SPA SPA(single page web application)单页 Web 应用,Web 不再是一张张页面,而是一个整体的应用,一个由路由系统、数据系统、页面(组件)系统等等,组成的应…...
java导出word使用模版与自定义联合出击解决复杂表格!
1. 看一下需要导出什么样子的表格 如图所示,这里的所有数据行都是动态的,需要根据查询出来的数据循环展示。 如果只是这样的话,使用freemarker应该都可以搞定,但是他一列中内容相同的单元格,需要合并。 这对于表格样式…...
GO设计模式——9、过滤器模式(结构型)
目录 过滤器模式(Filter/Criteria Pattern) 代码实现 过滤器模式(Filter/Criteria Pattern) 过滤器模式(Filter Pattern)或标准模式(Criteria Pattern)是一种设计模式,…...
fastadmin 导出
php 接收数据 set_time_limit(0);ini_set(memory_limit, -1);$ids $this->request->post(ids);$filter $this->request->post(filter);$op $this->request->post(op);$search $this->request->post(search);$whereIds $ids all ? 11 : [id >…...
六、CM4树莓派USBRS转485串口通讯
一、串行通讯接口 串行通讯接口简称串口(UART) 采用串行通信方式的扩展接口,数据位一位一位的按照顺序传送 优点:通信线路简单,只要一对传输线就可以实现双向通信能够大大降低成本,适合远距离通信。 缺点…...
c++知识总结
一 细碎知识 1.27 # 1.27.1 # pragma once 参考 C++学习笔记之pragma once的理解_pragma once什么意思-CSDN博客https://blog.csdn.net/lynnlee_36/article/details/105322937作用 保证只被编译一次,和#ifndef,#define,#endif功能相同 1.27.2 #if defined(__cplusplus…...
python-爬取壁纸
代理池的,防止IP 被封 找到图片真实地址 现在看到的只是图片的预览地址 (previews) 1.检查: 2.鼠标变为箭头时查看网页源代码 关于怎样在源代码中找到图片的真实地址 ??? 为什么在源代码界面 ctrl f 时候搜索的是 .png ??? 首先图片地址是以 .j…...
第31期 | GPTSecurity周报
GPTSecurity是一个涵盖了前沿学术研究和实践经验分享的社区,集成了生成预训练Transformer(GPT)、人工智能生成内容(AIGC)以及大型语言模型(LLM)等安全领域应用的知识。在这里,您可以…...
湖仓一体架构理论与实践汇总
湖仓一体架构理论与实践汇总 软件研发本质上属于“手工业”。软件研发在很大程度上还是依赖于个人的能力。当软件规模较小时,依赖“手工业”可以解决问题,但是当软件规模大了之后再依赖“手工业”就不行了。 软件的复杂度包含两个层面:软件…...
Redission从入门到入门
1. Redisson简介 Redisson 是一个在 Java 环境中使用的 Redis 客户端库。它提供了丰富的功能,使得在 Java 应用中与 Redis 交互变得更加简单和高效。Redisson 不仅提供了基本的 Redis 操作,还提供了许多高级功能,使其成为在 Java 项目中实现…...
C++_核心编程_多态案例二-制作饮品
#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为:煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例,提供抽象制作饮品基类,提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...
Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
Java入门学习详细版(一)
大家好,Java 学习是一个系统学习的过程,核心原则就是“理论 实践 坚持”,并且需循序渐进,不可过于着急,本篇文章推出的这份详细入门学习资料将带大家从零基础开始,逐步掌握 Java 的核心概念和编程技能。 …...
智能仓储的未来:自动化、AI与数据分析如何重塑物流中心
当仓库学会“思考”,物流的终极形态正在诞生 想象这样的场景: 凌晨3点,某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径;AI视觉系统在0.1秒内扫描包裹信息;数字孪生平台正模拟次日峰值流量压力…...
九天毕昇深度学习平台 | 如何安装库?
pip install 库名 -i https://pypi.tuna.tsinghua.edu.cn/simple --user 举个例子: 报错 ModuleNotFoundError: No module named torch 那么我需要安装 torch pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple --user pip install 库名&#x…...
【C++进阶篇】智能指针
C内存管理终极指南:智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...
4. TypeScript 类型推断与类型组合
一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式,自动确定它们的类型。 这一特性减少了显式类型注解的需要,在保持类型安全的同时简化了代码。通过分析上下文和初始值,TypeSc…...
Matlab实现任意伪彩色图像可视化显示
Matlab实现任意伪彩色图像可视化显示 1、灰度原始图像2、RGB彩色原始图像 在科研研究中,如何展示好看的实验结果图像非常重要!!! 1、灰度原始图像 灰度图像每个像素点只有一个数值,代表该点的亮度(或…...
Spring Boot 与 Kafka 的深度集成实践(二)
3. 生产者实现 3.1 生产者配置 在 Spring Boot 项目中,配置 Kafka 生产者主要是配置生产者工厂(ProducerFactory)和 KafkaTemplate 。生产者工厂负责创建 Kafka 生产者实例,而 KafkaTemplate 则是用于发送消息的核心组件&#x…...
LeetCode--25.k个一组翻转链表
解题思路: 1.获取信息: (1)给定一个链表,每k个结点一组进行翻转 (2)余下不足k个结点,则不进行交换 2.分析题目: 其实就是24题的变题,24题是两两一组进行交换&…...



