当前位置: 首页 > article >正文

Java反射机制详解:原理、应用与最佳实践

Java反射机制详解:原理、应用与最佳实践

1. 什么是反射?

Java反射(Reflection)是指在运行时动态获取类的信息(如类名、方法、字段、构造方法等)并操作对象的能力。它允许程序在运行时检查和修改类的行为,而不需要在编译时知道类的具体结构。

1.1 反射的核心类

  • Class<T>:表示一个类或接口。
  • Field:表示类的成员变量。
  • Method:表示类的方法。
  • Constructor<T>:表示类的构造方法。
  • Modifier:提供访问修饰符(如publicprivate等)的方法。

2. 反射的基本使用

2.1 获取Class对象的三种方式

// 方式1:通过类名.class
Class<String> strClass = String.class;// 方式2:通过对象.getClass()
String str = "Hello";
Class<?> strClass2 = str.getClass();// 方式3:通过Class.forName("全限定类名")
Class<?> strClass3 = Class.forName("java.lang.String");

2.2 获取类的信息

Class<?> clazz = String.class;// 获取类名
String className = clazz.getName(); // "java.lang.String"// 获取所有public方法
Method[] methods = clazz.getMethods();// 获取所有字段(包括private)
Field[] fields = clazz.getDeclaredFields();// 获取所有构造方法
Constructor<?>[] constructors = clazz.getDeclaredConstructors();

2.3 动态创建对象

Class<?> clazz = Class.forName("java.lang.String");
Constructor<?> constructor = clazz.getConstructor(String.class);
String str = (String) constructor.newInstance("Hello");
System.out.println(str); // 输出 "Hello"

2.4 动态调用方法

Class<?> clazz = String.class;
Method method = clazz.getMethod("toUpperCase");
String str = "hello";
String upperStr = (String) method.invoke(str);
System.out.println(upperStr); // 输出 "HELLO"

2.5 访问和修改私有字段

class Person {private String name = "Alice";
}// 获取并修改私有字段
Person person = new Person();
Class<?> clazz = person.getClass();
Field field = clazz.getDeclaredField("name");// 设置可访问(绕过private限制)
field.setAccessible(true);// 获取和修改值
String name = (String) field.get(person);
System.out.println(name); // "Alice"field.set(person, "Bob");
System.out.println(person.getName()); // "Bob"(如果有getter)

3. 反射的应用场景

3.1 动态代理(如Spring AOP)

interface Greeting {void sayHello();
}class Hello implements Greeting {public void sayHello() {System.out.println("Hello!");}
}// 动态代理
Greeting proxy = (Greeting) Proxy.newProxyInstance(Hello.class.getClassLoader(),new Class[]{Greeting.class},(proxyObj, method, args) -> {System.out.println("Before method");Object result = method.invoke(new Hello(), args);System.out.println("After method");return result;}
);proxy.sayHello();
// 输出:
// Before method
// Hello!
// After method

3.2 注解处理(如JUnit、Lombok)

@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation {String value();
}@MyAnnotation("Test")
class MyClass {}// 读取注解
Class<?> clazz = MyClass.class;
MyAnnotation annotation = clazz.getAnnotation(MyAnnotation.class);
System.out.println(annotation.value()); // "Test"

3.3 框架开发(如Spring IOC)

Spring通过反射动态加载Bean:

Class<?> beanClass = Class.forName("com.example.MyBean");
Object bean = beanClass.getDeclaredConstructor().newInstance();
// 然后存入IOC容器

4. 反射的优缺点

4.1 优点

动态性:可以在运行时动态加载类、调用方法、修改字段。
灵活性:适用于框架开发(如Spring、Hibernate)。
绕过访问限制:可以访问private成员(但需谨慎)。

4.2 缺点

性能较低:反射比直接调用方法慢(JVM无法优化)。
安全性问题:可能破坏封装性(如修改private字段)。
代码可读性差:反射代码较难维护。


5. 反射的性能优化

由于反射调用比普通方法调用慢,可以采用以下优化方式:

  1. 缓存ClassMethodField对象(避免重复查找)。
  2. 使用MethodHandle(Java 7+)
    MethodHandles.Lookup lookup = MethodHandles.lookup();
    MethodHandle methodHandle = lookup.findVirtual(String.class, "toUpperCase", MethodType.methodType(String.class));
    String result = (String) methodHandle.invoke("hello");
    System.out.println(result); // "HELLO"
    
  3. 尽量少用反射,仅在必要时使用。

6. 总结

特性说明
获取Class对象Class.forName() / obj.getClass() / ClassName.class
创建对象clazz.newInstance() / constructor.newInstance()
调用方法method.invoke(obj, args)
访问字段field.get(obj) / field.set(obj, value)
动态代理Proxy.newProxyInstance()
性能优化缓存反射对象 / 使用MethodHandle

反射是Java强大的特性,广泛应用于框架开发,但需谨慎使用以避免性能和安全问题。🚀


📌 推荐阅读:

  • Oracle官方反射教程
  • 《Effective Java》- 反射的最佳实践

💬 讨论: 你在项目中如何使用反射?欢迎在评论区交流!👇

相关文章:

Java反射机制详解:原理、应用与最佳实践

Java反射机制详解&#xff1a;原理、应用与最佳实践 1. 什么是反射&#xff1f; Java反射&#xff08;Reflection&#xff09;是指在运行时动态获取类的信息&#xff08;如类名、方法、字段、构造方法等&#xff09;并操作对象的能力。它允许程序在运行时检查和修改类的行为&…...

Swift实现嵌套json字典重排序并输出string

在网络请求或接口签名中&#xff0c;通常要求将参数按照一定规则拼接成字符串。一个常见的做法是对字典的 key 进行排序&#xff0c;然后按照 “keyvalue” 的格式拼接&#xff0c;多个参数之间以特定符号&#xff08;例如 &&#xff09;连接。 如果参数中包含嵌套的字典或…...

【Ai】--- 可视化 DeepSeek-r1 接入 Open WebUI(超详细)

在编程的艺术世界里,代码和灵感需要寻找到最佳的交融点,才能打造出令人为之惊叹的作品。而在这座秋知叶i博客的殿堂里,我们将共同追寻这种完美结合,为未来的世界留下属于我们的独特印记。【Ai】--- 可视化 DeepSeek-r1 接入 Open WebUI(超详细) 开发环境一、前情提要:你…...

VSCode加Cline插件加DeepSeek实现AI编程指南

VSCode加Cline插件加DeepSeek实现AI编程指南 简介 本文将详细介绍如何在VSCode中使用Cline插件结合DeepSeek AI实现高效的AI辅助编程&#xff0c;特别适合初学者快速上手。我们将通过实现一个TodoList应用的例子来演示整个流程。 环境准备 1. 安装VSCode 前往VSCode官网下…...

代码规范之Variable Names变量名

代码规范之Variable Names变量名 golang中 官方文档&#xff1a;https://go.dev/wiki/CodeReviewComments#variable-names Variable names in Go should be short rather than long. This is especially true for local variables with limited scope. Prefer c to lineCoun…...

2025春招市场迎AI热潮:生成式人工智能(GAI)认证如何重构人才竞争力

随着科技的飞速发展&#xff0c;人工智能&#xff08;AI&#xff09;已逐渐渗透到我们生活的方方面面&#xff0c;从智能家居到自动驾驶&#xff0c;从智能客服到医疗诊断&#xff0c;AI的身影无处不在。而在这股AI浪潮中&#xff0c;生成式人工智能&#xff08;Generative AI,…...

Flink基础简介和安装部署

文章目录 一、Flink基础简介1、什么是Flink2、Flink流处理特性3、Flink四大基石4、Flink中的角色 二、Flink集群搭建1、Local模式①上传Flink安装包②启动交互窗口③提交任务测试④访问WebUI页面查看⑤退出停止集群 2、Standalone模式①修改配置⽂件 conf/flink-conf.yaml②修改…...

SpringBoot分布式项目实战:观察者模式的高阶应用与避坑指南

一、痛点场景&#xff1a;当观察者遇上分布式 在某电商平台重构项目中&#xff0c;我们遭遇了这样的困境&#xff1a;订单中心完成支付后需要触发库存扣减、积分结算、物流调度等12个后续操作。最初的实现采用了硬编码调用&#xff1a; // 伪代码示例 public void paySuccess…...

How to use pgbench to test performance for PostgreSQL?

pgbench 是一个用于测试 PostgreSQL 数据库性能的基准测试工具。通过模拟多个客户端并发执行 SQL 查询&#xff0c;它可以帮助你评估数据库的性能。以下是使用 pgbench 的基本步骤&#xff1a; 安装 pgbench pgbench 是 PostgreSQL 的一部分&#xff0c;因此在安装 PostgreSQ…...

C#基础学习(五)函数中的ref和out

1. 引言&#xff1a;为什么需要ref和out&#xff1f; ​问题背景&#xff1a;函数参数默认按值传递&#xff0c;值类型在函数内修改不影响外部变量&#xff1b;引用类型重新赋值时外部对象不变。​核心作用&#xff1a;允许函数内部修改外部变量的值&#xff0c;实现“双向传参…...

从零构建大语言模型全栈开发指南:第二部分:模型架构设计与实现-2.2.2文本生成逻辑:Top-k采样与温度控制

👉 点击关注不迷路 👉 点击关注不迷路 👉 点击关注不迷路 文章大纲 2.2.2 文本生成逻辑:Top-k采样与温度控制1. 文本生成的核心挑战与数学框架1.1 自回归生成的基本流程2. `Top-k`采样原理与工程实现2.1 数学定义与算法流程2.2 PyTorch实现优化3. 温度控制的数学本质与参…...

关于CodeJava的学习笔记——9

一、IO流 1、定义 IInput输入 OOutput输出 流 : 数据从源点传输到汇点的"管道"而已 2、流的分类 按照方向分: 输入流 输出流 *:参照物当前Java程序为参照物 按照单位分: 字节流 字符流 按照功能分: 节点流 过滤流(包装流 处…...

LeetCode算法题(Go语言实现)_11

题目 给定字符串 s 和 t &#xff0c;判断 s 是否为 t 的子序列。 字符串的一个子序列是原始字符串删除一些&#xff08;也可以不删除&#xff09;字符而不改变剩余字符相对位置形成的新字符串。&#xff08;例如&#xff0c;"ace"是"abcde"的一个子序列&a…...

Python----数据分析(足球运动员数据分析)

一、数据展示 1.1、数据 1.2、列名 字段名备注Name姓名Nationality国籍National_Position国家队位置National_Kit国家队号码Club所在俱乐部Club_Position所在俱乐部位置Club_Kit俱乐部号码Club_Joining加入俱乐部时间Contract_Expiry合同到期时间Rating评分Height身高Weight体…...

Day38 | 1365. 有多少小于当前数字的数字、941. 有效的山脉数组、1207. 独一无二的出现次数、283. 移动零、189. 轮转数组

1365. 有多少小于当前数字的数字 题目链接&#xff1a;1365. 有多少小、于当前数字的数字 - 力扣&#xff08;LeetCode&#xff09; 题目难度&#xff1a;简单 代码&#xff1a; class Solution {public int[] smallerNumbersThanCurrent(int[] nums) {Map<Integer,Inte…...

Docker-清理容器空间prune

docker system prune -a 是一个非常有用的命令&#xff0c;用于清理 Docker 系统中未使用的资源&#xff0c;包括停止的容器、未使用的网络、卷以及未被任何容器引用的镜像&#xff08;悬空镜像和所有未使用的镜像&#xff09;。以下是关于该命令的详细说明&#xff1a; 命令格…...

matplotlib——南丁格尔玫瑰

南丁格尔玫瑰图&#xff08;Nightingale Rose Chart&#xff09;&#xff0c;是一种特殊形式的柱状图&#xff0c;它以南丁格尔&#xff08;Florence Nightingale&#xff09;命名&#xff0c;她在1858年首次使用这种图表来展示战争期间士兵死亡原因的数据。 它将数据绘制在极坐…...

Django与网页表单

我叫补三补四&#xff0c;很高兴见到大家&#xff0c;欢迎一起学习交流和进步 今天来讲一讲网页表单 网页表单又叫做HTML表单&#xff0c;用来处理用户从页面输入发送到服务器的数据&#xff0c;页面表单通常会提供复选框、单选按钮和文本字段&#xff0c;方便用户填写各种形式…...

Rust从入门到精通之入门篇:10.包和模块

包和模块 在本章中&#xff0c;我们将学习 Rust 的包和模块系统&#xff0c;它们是组织和重用代码的重要工具。随着项目规模的增长&#xff0c;良好的代码组织变得越来越重要&#xff0c;Rust 提供了一套强大的机制来管理代码结构。 包和 Crate Crate Crate 是 Rust 中最高…...

ChatDBA VS DeepSeek:快速诊断 OceanBase 集群新租户数据同步异常

社区王牌专栏《一问一实验&#xff1a;AI 版》改版以来已发布多期&#xff08;51-60&#xff09;&#xff0c;展现了 ChatDBA 在多种场景下解决问题的效果。 下面让我们正式进入《一问一实验&#xff1a;AI 版》第 62 期&#xff0c;看看 ChatDBA 最新效果以及与热门大模型 De…...

dify忘记密码

特别好&#xff0c;非常好&#xff0c;一把年纪忘了dify的账号、密码了&#xff0c;very good&#xff01;&#xff01;&#xff01; 参考如下教程 https://zhuanlan.zhihu.com/p/24515387167 rootbae577d82ec7:/# psql -U postgres psql: error: connection to server on so…...

Python----计算机视觉处理(Opencv:图像边缘检测:非极大值抑制,双阈值筛选)

一、 高斯滤波 边缘检测本身属于锐化操作&#xff0c;对噪点比较敏感&#xff0c;所以需要进行平滑处理。这里使用的是一个5*5的高斯 核对图像进行消除噪声。 二、计算图像的梯度和方向 三、非极大值抑制 在得到每个边缘的方向之后&#xff0c;其实把它们连起来边缘检测就算完了…...

vue3(笔记)5.0--pinia工具的知识扩展

pinia工具 defineStore(创建pinia) 作用&#xff1a;用于定义一个 Pinia store。 用法&#xff1a; 接收一个唯一的 ID 和一个配置对象&#xff0c;配置对象中可以定义 state、getters 和 actions。state 是一个函数&#xff0c;返回初始状态。getters 类似于 Vue 组件中的计…...

基于Kubernetes部署Prometheus监控平台

#作者&#xff1a;stackofumbrella 文章目录 prometheus和k8s集群版本对照表架构Prometheus Operator简介kube-prometheus下载地址 安装修改镜像地址修改Prometheus的service修改Grafana的service修改Alertmanager的service数据持久化执行安装 Prometheus验证Grafana验证解决C…...

往期项目shader着色器实践效果应用合集

1、管路混色 2、水管水流效果 3、水管流入到流完效果 4、加热冷却 两 色混色 示意 XX、毒蘑菇测试效果...

如何在 React 项目中使用React.lazy和Suspense实现组件的懒加载?

大白话如何在 React 项目中使用React.lazy和Suspense实现组件的懒加载&#xff1f; 在 React 项目里&#xff0c;有时候组件功能多、体积大&#xff0c;要是一次性把所有组件都加载进来&#xff0c;网页加载速度就会变慢。而 React 提供了 React.lazy 和 Suspense 这两个好东西…...

绿色暴政:Relax Max如何用军工科技定义环保新标准

《绿色暴政&#xff1a;Relax Max如何用军工科技定义环保新标准》 ——从隐形战斗机涂层到零碳卫浴的降维打击 &#xff08;洛克希德马丁实验室&#xff0c;2023年&#xff09;当F-35战斗机的隐形涂料配方被改写为卫浴釉料时&#xff0c;环保产业迎来了最硬核的颠覆者。Relax…...

蓝桥杯刷题 Day 4 栈与链表

蓝桥杯刷题 Day 4 栈与链表 文章目录 蓝桥杯刷题 Day 4 栈与链表前言一、栈1. 解题思路2. 拆解代码&#xff08;不复杂&#xff0c;不拆了&#xff09; 二、链表1. 解题思路1.1 主函数1.2 自定义列表类1.2.1 插入操作1.2.2 删除操作1.2.3 按要求输出 三、 题后收获3.1 知识点 前…...

第十三届蓝桥杯单片机省赛程序设计试题

目录 试题 各程序块代码 init.c main.c other.h other.c key.c seg.c onewire.c部分 ds1302.c部分 试题 各程序块代码 init.c #include "other.h"void init74hc138(unsigned char n){P2(P2&0x1f)|(n<<5);P2&0x1f; } void init(){P00x00;in…...

QOpenGLWidget动态加载功能实现教程(Qt+OpenGL)

QOpenGLWidget动态加载功能实现教程 我需要在Qt里面使用QOpenGLWidget显示OpenGL窗口&#xff0c;并且需要实现加载模型后重新渲染更新窗口的功能&#xff0c;但是一直无法更新被卡住了&#xff0c;现在把问题解决了总结一下整个实现过程。 创建一个自己的OpenGLWidget类 QOp…...