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

java反射学习总结

最近在项目上有一个内部的CR,运用到了反射。想起之前面试的时候被面试官追问有没有在项目中用过反射,以及反射的原理和对反射的了解。

于是借此机会,学习回顾一下反射,以及在项目中可能会用到的场景。

 Java 中的反射概述

反射(Reflection) 是 Java 提供的一种机制,它允许程序在运行时动态地检查和操作类的属性、方法以及构造函数等信息。反射使得我们可以在编译时不确定类型的情况下操作对象,比如动态地调用方法、访问属性和创建对象实例。

反射的核心类和接口

反射主要依赖于以下几个类和接口:

  • Class<?>:代表一个类的字节码对象,通过它可以获取类的名称、方法、字段、构造函数等信息。
  • Field:表示类的属性,可以通过它获取或修改某个对象的字段值。
  • Method:表示类的方法,可以通过它调用类的某个方法。
  • Constructor<?>:表示类的构造函数,可以通过它创建类的实例。

反射的主要功能

  • 获取类的结构信息:包括类名、包名、父类、实现的接口等。
  • 获取类的成员信息:包括属性(Field)、方法(Method)、构造函数(Constructor)等。
  • 动态操作对象:包括创建实例、调用方法、修改属性值等。

反射的常用方法

获取类对象 :

Class<?> clazz = Class.forName("com.example.MyClass"); // 通过类的全限定名获取
Class<?> clazz = MyClass.class; // 通过类名.class获取
Class<?> clazz = object.getClass(); // 通过对象实例获取

 获取类的构造函数

Constructor<?> constructor = clazz.getConstructor(); // 获取无参构造函数
Constructor<?> constructor = clazz.getConstructor(String.class); // 获取带参数的构造函数
Object instance = constructor.newInstance("arg"); // 创建类的实例

获取类的方法

Method method = clazz.getMethod("methodName", String.class); // 获取特定名称和参数的方法
method.invoke(instance, "arg"); // 调用方法

 获取类的属性

Field field = clazz.getDeclaredField("fieldName"); // 获取特定名称的属性
field.setAccessible(true); // 设置可访问性,忽略private修饰符
field.set(instance, "value"); // 设置属性值

反射的应用场景

  • 依赖注入(Dependency Injection:如 Spring 框架,通过反射机制在运行时动态地为类的属性赋值,完成依赖注入。
  • 框架设计(如ORM框架:如 Hibernate,通过反射获取实体类的字段和方法,将数据库表和实体类进行映射。
  • 动态代理(Dynamic Proxy:通过反射生成代理类,增强方法的功能,应用于 AOP(面向切面编程)等。
  • 运行时动态操作:在运行时根据配置文件或用户输入动态调用指定的方法,常用于插件化、动态加载等场景。
  • 测试框架(如JUnit:JUnit 等测试框架通过反射来调用测试方法,并通过反射访问私有成员变量以便进行单元测试。

反射的原理

 每个 Java 类在被加载时,JVM 会为该类生成一个唯一的 Class 对象,这个对象包含了类的所有元数据信息,如类名、包名、父类、接口、构造方法、字段、方法等。反射机制的基础就是利用 Class 对象来获取这些信息。

反射的基本操作流程

  • 获取 Class 对象:反射的第一步是获取代表某个类的 Class 对象。可以通过 Class.forName()、类名.class 或 对象.getClass() 来获取。

Class 对象是所有反射操作的基础。JVM 会为每一个被加载的类创建一个 Class 对象,Class 对象中存储了该类的所有元数据信息。

  1. Class.forName(String className):通过类的全限定名在运行时加载类并返回其 Class 对象。
  2. 类名.class:直接通过类名获取该类的 Class 对象。
  3. 对象.getClass():通过对象实例获取其对应的 Class 对象。

这些方法调用后都会返回 JVM 中已经存在的 Class 对象,而不会重新加载类。

  • 获取类的成员信息:通过 Class 对象的各种方法如 getDeclaredMethods()、getDeclaredFields() 等,可以获取类的所有方法、字段、构造函数等信息。

Class 对象中包含了类的所有元数据信息,可以通过以下方法获取:

//获取字段信息(Field):
Constructor<?> constructor = clazz.getDeclaredConstructor(参数类型.class);
//获取方法信息(Method):
Method method = clazz.getDeclaredMethod("methodName", 参数类型.class);
//获取构造函数信息(Constructor):
Field field = clazz.getDeclaredField("fieldName");

Field、Method 和 Constructor 对象中都包含了对应的详细信息(名称、类型、修饰符等),这些信息是 JVM 在类加载时解析字节码并存储在 Class 对象中的。

  • 动态操作:获取到类的结构信息后,可以通过 Method.invoke() 调用方法,通过 Field.set() 或 Field.get() 修改或访问字段,通过 Constructor.newInstance() 创建实例等。

调用方法

Method method = clazz.getDeclaredMethod("methodName", 参数类型.class);
method.setAccessible(true); // 如果方法是私有的,需要设置可访问性
Object result = method.invoke(instance, 参数); // 动态调用方法

反射调用方法的过程大致如下:

  1. 检查方法的可访问性,如果是私有方法则需要设置 setAccessible(true)
  2. 解析方法的参数类型,并匹配传递的参数是否符合要求。
  3. 调用 invoke 时,JVM 通过内部调用找到对应的本地方法实现,然后执行调用。

修改字段值

Field field = clazz.getDeclaredField("fieldName");
field.setAccessible(true); // 如果字段是私有的,需要设置可访问性
field.set(instance, value); // 动态修改字段值

修改字段值的过程:

  1. 检查字段的可访问性,如果是私有字段则需要设置 setAccessible(true)
  2. 调用 set() 时,JVM 将新值赋给对象的相应字段。

创建对象实例

Constructor<?> constructor = clazz.getDeclaredConstructor(参数类型.class);
constructor.setAccessible(true); // 如果构造函数是私有的,需要设置可访问性
Object instance = constructor.newInstance(参数); // 动态创建实例

创建对象实例的过程:

  1. 检查构造函数的可访问性,如果是私有构造函数则需要设置 setAccessible(true)
  2. 调用 newInstance() 时,JVM 内部调用本地方法创建对象,并初始化实例。

反射的局限性和问题

  • 性能问题: 反射在运行时解析类的元数据,因此其性能相对直接调用方法要低。频繁使用反射可能导致较大的性能开销。

  • 安全性问题: 反射可以绕过 Java 的访问控制检查,访问和修改类的私有成员。这可能导致安全隐患,特别是在不受信任的环境中。

  • 编译时类型检查缺失: 反射依赖于运行时类型信息,编译器无法对反射代码进行类型检查。这意味着在编译时可能无法检测出反射调用中的错误,只有在运行时才会抛出异常。

面对反射造成的错误该如何解决

  • ClassNotFoundException:类无法找到。

    • 确保类名(包括包名)拼写正确。
    • 确保类在类路径中存在。
  • NoSuchMethodException / NoSuchFieldException:方法或字段不存在。

    • 检查方法名、字段名以及参数类型是否匹配。
    • 确保访问的成员确实存在于目标类中。
  • IllegalAccessException:非法访问异常。

    • 确保 setAccessible(true) 已调用。
    • 确保 JVM 安全管理器允许修改私有成员。
  • InvocationTargetException:目标方法内部抛出异常。

    • 调用 getCause() 获取实际异常,并检查目标方法内部的逻辑。
  • InstantiationException:无法实例化对象。

    • 检查是否试图实例化一个抽象类或接口。
    • 确保存在无参构造函数,或使用带参构造函数。

总结

反射机制是 Java 强大的动态编程功能之一,它允许我们在运行时检查和操作类的结构信息,这在构建灵活的框架和库时非常有用。然而,反射的使用会带来一定的性能和安全性问题,因此在使用时应尽量避免过度使用。理解反射的内部实现原理和应用场景,掌握应对反射相关错误的解决方法,可以更好地利用这一特性来解决实际问题

相关文章:

java反射学习总结

最近在项目上有一个内部的CR&#xff0c;运用到了反射。想起之前面试的时候被面试官追问有没有在项目中用过反射&#xff0c;以及反射的原理和对反射的了解。 于是借此机会&#xff0c;学习回顾一下反射&#xff0c;以及在项目中可能会用到的场景。 Java 中的反射概述 反射&…...

探索C语言与Linux编程:获取当前用户ID与进程ID

探索C语言与Linux编程:获取当前用户ID与进程ID 一、Linux系统概述与用户、进程概念二、C语言与系统调用三、获取当前用户ID四、获取当前进程ID五、综合应用:同时获取用户ID和进程ID六、深入理解与扩展七、结语在操作系统与编程语言的交汇点,Linux作为开源操作系统的典范,为…...

1.4 边界值分析法

欢迎大家订阅【软件测试】 专栏&#xff0c;开启你的软件测试学习之旅&#xff01; 文章目录 前言1 定义2 选取3 具体步骤4 案例分析 本篇文章参考黑马程序员 前言 边界值分析法是一种广泛应用于软件测试中的技术&#xff0c;旨在识别输入值范围内的潜在缺陷。本文将详细探讨…...

Spring IOC容器Bean对象管理-注解方式

目录 1、Bean对象常用注解介绍 2、注解示例说明 1、Bean对象常用注解介绍 Component 通用类组件注解&#xff0c;该类被注解&#xff0c;IOC容器启动时实例化此类对象Controller 注解控制器类Service 注解业务逻辑类Respository 注解和数据库操作的类&#xff0c;如DAO类Reso…...

OpenAI API: How to catch all 5xx errors in Python?

题意&#xff1a;OpenAI API&#xff1a;如何在 Python 中捕获所有 5xx 错误&#xff1f; 问题背景&#xff1a; I want to catch all 5xx errors (e.g., 500) that OpenAI API sends so that I can retry before giving up and reporting an exception. 我想捕获 OpenAI API…...

C++初阶学习——探索STL奥秘——标准库中的priority_queue与模拟实现

1.priority_queque的介绍 1.priority_queue中文叫优先级队列。优先队列是一种容器适配器&#xff0c;根据严格的弱排序标准&#xff0c;它的第一个元素总是它所包含的元素中最大的。 2. 此上下文类似于堆&#xff0c;在堆中可以随时插入元素&#xff0c;并且只能检索最大堆元…...

PyTorch经典模型

PyTorch 经典模型教程 1. PyTorch 库架构概述 PyTorch 是一个广泛使用的深度学习框架&#xff0c;具有高度的灵活性和动态计算图的特性。它支持自动求导功能&#xff0c;并且拥有强大的 GPU 加速能力&#xff0c;适用于各种神经网络模型的训练与部署。 PyTorch 的核心架构包…...

C++ STL容器(三) —— 迭代器底层剖析

本篇聚焦于STL中的迭代器&#xff0c;同样基于MSVC源码。 文章目录 迭代器模式应用场景实现方式优缺点 UML类图代码解析list 迭代器const 迭代器非 const 迭代器 vector 迭代器const 迭代器非const迭代器 反向迭代器 迭代器失效参考资料 迭代器模式 首先迭代器模式是设计模式中…...

力扣416周赛

举报垃圾信息 题目 3295. 举报垃圾信息 - 力扣&#xff08;LeetCode&#xff09; 思路 直接模拟就好了&#xff0c;这题居然是中等难度 代码 public boolean reportSpam(String[] message, String[] bannedWords) {Map<String,Integer> map new HashMap<>()…...

vue 页面常用图表框架

在 Vue.js 页面中&#xff0c;常见的用于制作图表的框架或库有以下几种&#xff1a; ECharts: 官方网站: EChartsECharts 是一个功能强大、可扩展的图表库&#xff0c;支持多种图表类型&#xff0c;如柱状图、折线图、饼图等。Vue 集成: 可以使用 vue-echarts 插件&#xff0c;…...

spring 注解 - @PostConstruct - 用于初始化工作

PostConstruct 是 Java EE 5 中引入的一个注解&#xff0c;用于标注在方法上&#xff0c;表示该方法应该在依赖注入完成之后执行。这个注解是 javax.annotation 包的一部分&#xff0c;通常用于初始化工作&#xff0c;比如初始化成员变量或者启动一些后台任务。 在 Spring 框架…...

多机器学习模型学习

特征处理 import os import numpy as np import pandas as pd from sklearn.model_selection import train_test_split from sklearn.model_selection import StratifiedShuffleSplit from sklearn.impute import SimpleImputer from sklearn.pipeline import FeatureUnion fr…...

【网页设计】前言

本专栏主要记录 “网页设计” 这一课程的相关笔记。 参考资料&#xff1a; 黑马程序员&#xff1a;黑马程序员pink老师前端入门教程&#xff0c;零基础必看的h5(html5)css3移动端前端视频教程_哔哩哔哩_bilibili 教材&#xff1a;《Adobe创意大学 Dreamweaver CS6标准教材》《…...

STM32巡回研讨会总结(2024)

前言 本次ST公司可以说是推出了7大方面&#xff0c;几乎可以说是覆盖到了目前生活中的方方面面&#xff0c;下面总结下我的感受。无线类 支持多种调制模式&#xff08;LoRa、(G)FSK、(G)MSK 和 BPSK&#xff09;满足工业和消费物联网 (IoT) 中各种低功耗广域网 (LPWAN) 无线应…...

54 螺旋矩阵

解题思路&#xff1a; \qquad 这道题可以直接用模拟解决&#xff0c;顺时针螺旋可以分解为依次沿“右-下-左-上”四个方向的移动&#xff0c;每次碰到“边界”时改变方向&#xff0c;边界是不可到达或已经到达过的地方&#xff0c;会随着指针移动不断收缩。 vector<int>…...

基于STM32与OpenCV的物料搬运机械臂设计流程

一、项目概述 本文提出了一种新型的物流搬运机器人&#xff0c;旨在提高物流行业的物料搬运效率和准确性。该机器人结合了 PID 闭环控制算法与视觉识别技术&#xff0c;能够在复杂的环境中实现自主巡线与物料识别。 项目目标与用途 目标&#xff1a;设计一款能够自动搬运物流…...

[万字长文]stable diffusion代码阅读笔记

stable diffusion代码阅读笔记 获得更好的阅读体验可以转到我的博客y0k1n0的小破站 本文参考的配置文件信息: AutoencoderKL:stable-diffusion\configs\autoencoder\autoencoder_kl_32x32x4.yaml latent-diffusion:stable-diffusion\configs\latent-diffusion\lsun_churches-ld…...

watchEffect工作原理

watchEffect工作原理 自动依赖收集&#xff1a;watchEffect不需要明确指定要观察的响应式数据&#xff0c;它会自动收集回调函数中用到的所有响应式数据作为依赖。即时执行&#xff1a;watchEffect的回调函数会在组件的setup()函数执行时立即执行一次&#xff0c;以便能够立即…...

斐波那契数列

在 Python 3.11 中实现斐波那契数列的常见方式有多种&#xff0c;下面我将展示几种不同的实现方法&#xff0c;包括递归、迭代和使用缓存&#xff08;动态规划&#xff09;来优化递归版本。 1. 递归方式&#xff08;最简单但效率较低&#xff09; def fibonacci_recursive(n)…...

TCP并发服务器的实现

一请求一线程 问题 当客户端数量较多时&#xff0c;使用单独线程为每个客户端处理请求可能导致系统资源的消耗过大和性能瓶颈。 资源消耗&#xff1a; 线程创建和管理开销&#xff1a;每个线程都有其创建和销毁的开销&#xff0c;特别是在高并发环境中&#xff0c;这种开销…...

5步掌握Loop:让Mac窗口管理效率提升10倍的免费开源方案

5步掌握Loop&#xff1a;让Mac窗口管理效率提升10倍的免费开源方案 【免费下载链接】Loop MacOS窗口管理 项目地址: https://gitcode.com/GitHub_Trending/lo/Loop 在数字工作环境中&#xff0c;窗口管理已成为影响效率的隐形瓶颈。Mac用户每天平均需要执行200次窗口操作…...

BGE Reranker-v2-m3开发者案例:为LangChain添加本地重排序节点的5步集成法

BGE Reranker-v2-m3开发者案例&#xff1a;为LangChain添加本地重排序节点的5步集成法 1. 项目背景与核心价值 在构建检索增强生成&#xff08;RAG&#xff09;系统时&#xff0c;文本相关性排序是决定最终效果的关键环节。传统的基于向量相似度的检索往往无法准确捕捉查询与…...

WeChatExporter:免费开源工具,轻松备份你的微信聊天记录到电脑

WeChatExporter&#xff1a;免费开源工具&#xff0c;轻松备份你的微信聊天记录到电脑 【免费下载链接】WeChatExporter 一个可以快速导出、查看你的微信聊天记录的工具 项目地址: https://gitcode.com/gh_mirrors/wec/WeChatExporter 你是否曾经担心过手机丢失、系统崩…...

Ollama一键部署translategemma-27b-it:图文翻译模型在国产统信UOS验证通过

Ollama一键部署translategemma-27b-it&#xff1a;图文翻译模型在国产统信UOS验证通过 1. 开篇&#xff1a;当翻译遇上图文对话 想象一下&#xff0c;你拿到一份产品说明书&#xff0c;上面有中文文字和复杂的图表。你需要把它翻译成英文&#xff0c;但传统的翻译工具只能处理…...

5个高效能的LabelImg图像标注效率提升实践

5个高效能的LabelImg图像标注效率提升实践 【免费下载链接】labelImg LabelImg is now part of the Label Studio community. The popular image annotation tool created by Tzutalin is no longer actively being developed, but you can check out Label Studio, the open s…...

DeepSeek-R1-Distill-Qwen-7B效果展示:复杂问题推理实测

DeepSeek-R1-Distill-Qwen-7B效果展示&#xff1a;复杂问题推理实测 1. 模型能力概览 DeepSeek-R1-Distill-Qwen-7B是DeepSeek团队基于Qwen架构开发的7B参数推理模型&#xff0c;通过强化学习训练和知识蒸馏技术优化&#xff0c;在数学推理、代码生成和逻辑分析任务上展现出卓…...

163MusicLyrics全能工具:三步搞定音乐歌词高效解决方案

163MusicLyrics全能工具&#xff1a;三步搞定音乐歌词高效解决方案 【免费下载链接】163MusicLyrics Windows 云音乐歌词获取【网易云、QQ音乐】 项目地址: https://gitcode.com/GitHub_Trending/16/163MusicLyrics 163MusicLyrics是一款专注于音乐歌词获取与管理的开源…...

Cookie 和 Session 分别存储在客户端还是服务端?

从“存包凭条”到“后台存包柜”&#xff1a;Cookie 与 Session 的存储位置深度剖析1. 引言&#xff1a;超市存包处的“凭条”与“存包柜”2. 前置知识&#xff1a;HTTP 的“健忘症”3. Cookie&#xff1a;客户端的“小凭条”3.1 是什么&#xff1f;3.2 解决什么问题&#xff1…...

大模型核心技术概述:Token、Prompt、Tool与Agent的关系详解

你是不是经常听人聊AI时蹦出这些词&#xff1a;LLM、Token、Context、Prompt、Tool、MCP、Agent&#xff1f;听着好像都认识&#xff0c;但真要问“这到底是啥”&#xff0c;又有点懵。今天把这些词一个个拆开揉碎&#xff0c;讲清楚它们到底是啥、有啥用、又是怎么串起来的。 …...

深度解析:Live2D Widget WebSocket实时交互架构实践

深度解析&#xff1a;Live2D Widget WebSocket实时交互架构实践 【免费下载链接】live2d-widget 把萌萌哒的看板娘抱回家 (ノ≧∇≦)ノ | Live2D widget for web platform 项目地址: https://gitcode.com/gh_mirrors/li/live2d-widget 在当今Web应用追求沉浸式体验的浪潮…...