反射机制

news/2025/2/27 20:07:34/文章来源:https://www.cnblogs.com/kisssheep/p/18741834

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

一、反射的核心类

Java 反射的核心 API 位于 java.lang.reflect 包中,主要类包括:

  • Class<T>:表示一个类或接口的元数据。

  • Constructor<T>:表示类的构造方法。

  • Field:表示类的成员变量(字段)。

  • Method:表示类的方法。


二、获取 Class 对象的三种方式

  1. 通过类名获取

Class<?> clazz1 = String.class; // 直接通过类的静态属性获取

  1. 通过对象实例获取

String str = "Hello";

Class<?> clazz2 = str.getClass(); // 对象.getClass()

  1. 通过全限定类名动态加载

Class<?> clazz3 = Class.forName("java.lang.String"); // 需处理 ClassNotFoundException

因为在一个类在 JVM 中只会有一个 Class 实例,所以对 c1 、 c2 、 c3 进行 equals 比较时返回的都是

true 。


三、反射的核心功能

  1. 创建对象

// 获取无参构造方法并实例化

Class<?> clazz = Class.forName("com.example.User");

Constructor<?> constructor = clazz.getConstructor();

Object user = constructor.newInstance();

// 获取有参构造方法并实例化

Constructor<?> constructor = clazz.getConstructor(String.class, int.class);

Object user = constructor.newInstance("Alice", 25);

  1. 操作字段(包括私有字段)

// 获取字段并修改值

Field nameField = clazz.getDeclaredField("name");

nameField.setAccessible(true); // 暴力反射,突破私有权限

nameField.set(user, "Bob");

// 获取字段值

String name = (String) nameField.get(user);

  1. 调用方法(包括私有方法)

// 获取方法并调用

Method method = clazz.getDeclaredMethod("sayHello", String.class);

method.setAccessible(true); // 突破私有权限

Object result = method.invoke(user, "World"); // 调用实例方法

  1. 获取类信息

// 获取所有公共方法

Method[] methods = clazz.getMethods();

// 获取所有声明字段(包括私有)

Field[] fields = clazz.getDeclaredFields();

// 获取实现的接口

Class<?>[] interfaces = clazz.getInterfaces();


四、反射的优缺点

优点

  1. 动态性:运行时动态加载类、调用方法,适合框架和工具开发(如 Spring、Hibernate)。

  2. 灵活性:突破访问限制(如调用私有方法、修改私有字段)。

  3. 通用性:编写通用代码(如 JSON 序列化工具)。

缺点

  1. 性能开销:反射操作比直接调用慢(JVM 优化后差距缩小)。

  2. 安全性问题:破坏封装性,可能引发安全问题。

  3. 代码可读性差:反射代码通常难以维护。


五、反射的应用场景

  1. 框架开发

    1. Spring 的依赖注入(IoC):通过反射实例化 Bean 并注入属性。

    2. MyBatis 的 ORM 映射:动态设置查询结果到对象字段。

    3. Spring 中的xml的配置模式

  2. 动态代理

    1. 结合 ProxyInvocationHandler 实现动态代理(如 AOP)。
  3. 注解处理器

    1. 解析自定义注解并执行逻辑(如 JUnit 的 @Test)。
  4. 通用工具类

    1. 序列化/反序列化工具(如 Jackson、Gson)。

    2. 数据库连接池的通用查询方法。


六、示例:通过反射调用私有方法

public class Demo {

private String secret() {

return "Confidential Data";

}

}

// 反射调用

public class ReflectionTest {

public static void main(String[] args) throws Exception {

Class<?> clazz = Class.forName("com.example.Demo");

Object obj = clazz.getDeclaredConstructor().newInstance();

Method method = clazz.getDeclaredMethod("secret");

method.setAccessible(true); // 突破私有权限

String result = (String) method.invoke(obj);

System.out.println(result); // 输出: Confidential Data

}

}


七、注意事项

  1. 性能优化

    1. 缓存反射获取的 MethodField 对象,避免重复查找。

    2. 优先使用直接调用,反射仅用于必要场景。

  2. 安全管理

    1. 通过 SecurityManager 限制反射权限(如禁止修改私有字段)。
  3. 版本兼容性

    1. Java 9+ 模块化系统可能限制反射访问,需在 module-info.java 中声明 opens

总结(ds学习记录)

Java 反射是强大的动态编程工具,但需谨慎使用。核心价值在于灵活性和动态性,适用于框架和通用工具开发,但在业务代码中应尽量避免滥用。

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

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

相关文章

题解:P4586 [FJOI2015] 最小覆盖双圆问题

写了这么久终于过了,发篇题解记录一下。 第一次写黑题题解,写的不好请见谅。 目录本题思路 三点定圆 最小圆覆盖 关于最小圆覆盖时间复杂度 回到本题 二分法划分点集 总时间复杂度 最小覆盖双圆问题代码本题思路 首先,这道题叫做最小覆盖双圆问题,这道题涉及到一个叫做最小…

sed undefined label on MacOS, FreeBSD

A quick fix is to prepend your string expression with an empty string: For example: instead of sed -i s/foo/bar/g text.txt write: sed -i s/foo/bar/g text.txtThis should work across different OS (Linux, MacOS, Windows) --dopexxx来源:http://stackoverflow.…

软工作业1:自我介绍+软工5问

这个作业属于哪个课程 软工23级这个作业要求在哪里 自我介绍+软工五问这个作业的目标 熟悉博客园以及Github的相关操作,了解软件工程相关内容1.自我介绍兴趣爱好:羽乒人,爱听歌,电影,楷书,行楷 编程语言:C,JAVA 目标:后端开发2.软工五问软件工程在对就业上的帮助的具体…

对“推箱子”小游戏代码的改进

一.代码来源 https://www.cnblogs.com/heyu123/p/14844284.html 二.运行环境 DEV--C++ 三.原代码及其运行结果 原代码: int map[8][8]={{1,1,1,1,1,1,1,1},//0 空地 {1,0,0,0,1,0,0,1},//1 墙 {1,0,1,0,1,4,3,1},//3 目的地 {1,0,0,0,0,4,3,1},//4 箱子 {1,0,1,0,1,4,3,1},//5…

软件开发与创新课程设计作业——软件逆向设计

一、来源:软件工程2班李鹏飞去年的大作业`点击查看代码 #include <iostream> #include <string> #include <fstream> using namespace std;//定义客户类型 enum eGuestType // 在高版本VS中,需要用enum class,在低版本的vs中,直接用enum也可以 {e_member…

LVI_SAM 虚拟机安装复现(一)

0. 前言 高能警告:LVI_SAM 的安装步骤是繁琐的,一个坑接着一个坑,请预留48+小时的安装时间,和80%以上的san值。非战斗人员请尽快撤离。 预备知识:虚拟机安装步骤,ROS基本概念,Makefile工作原理 没有预备知识的话,也没关系,本文也不会给你解释的( 本文是第一大步骤,即…

大模型--三种三种检索方式-Dense retrieval / Lexical Retrieval / Multi-Vector Retrieval- 44

1. 参考 M3-Embedding https://github.com/FlagOpen/FlagEmbedding https://arxiv.org/pdf/2402.03216 https://huggingface.co/BAAI/bge-m3 2. Dense retrievalimport torch import torch.nn as nnclass DenseRetrieval(nn.Module):def __init__(self, embedding_dim):super(D…

从拉新到留存,用户生命周期分析全流程

已收藏分享从拉新到留存,用户生命周期分析全流程 2025-02-17 17:02人人都是产品经理在当今竞争激烈的市场环境中,理解并管理用户生命周期是实现用户增长和留存的关键。本文将深入剖析用户生命周期的全流程管理,从拉新到留存,详细解读不同业务类型(如消费品、耐用品、平台型…

朴素贝叶斯其实并不朴素

朴素贝叶斯英文名称NaiveBayes,朴素贝叶斯确实nave,但是并不朴素,而是简单,并不是逻辑上面的简单,而是假设上面的简单。 1.贝叶斯公式 ​ 其中: P(C|X)是类C在给定特征X下的后验概率。 P(X|C)是特征X在给定类C下的条件概率,也叫做似然。 P(C)是类C的先验概率。 P(X)是特…

NocoBase 本周更新汇总:新增路由管理

本周更新包括:支持为页面标签页配置权限,新增路由管理页面等。汇总一周产品更新日志,最新发布可以前往我们的博客查看。 NocoBase 目前更新包括的版本更新包括三个分支:main ,next和 develop。main :截止目前最稳定的版本,推荐安装此版本。 next:包含即将发布的新功能,…

AI安全-模型用户输入注入

顾名思义,在调用AI大模型时,根据用户传入的数据,进行AI处理,调用插件,但模型后端需要调用API,API需要传入的username一个小场景,企业微信对话调用AI去修改当前密码 假设开发者设计如下: 用户输入-> AI -> 调用插件修改密码 修改密码插件实现:a.com/change_passw…