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

了解Java中的反射,带你如何使用反射

反射的定义

反射(Reflection)是Java的一种强大机制,它允许程序在运行时动态地查询和操作类的属性和方法。通过反射,Java程序可以获取类的信息,比如类的名称、方法、字段,以及可以动态地创建对象、调用方法和改变字段的值。

反射的主要用途包括:

  1. 动态加载类:在运行时加载类,而不需要在编译时确定。
  2. 查看类的结构:获取类的方法、字段、构造函数等信息,便于开发和调试。
  3. 实现通用代码:通过反射可以编写更为通用的代码,例如框架和库可以利用反射来实现插件或扩展机制。
  4. 访问和修改属性:可以在不知道对象具体类型的情况下,访问和修改其属性。

反射的实现一般通过Java的 java.lang.reflect 包进行,常用的类包括 ClassMethodField 和 Constructor 等。使用反射需要注意性能开销和安全问题,因此在使用时要权衡其必要性。

反射的用途

反射在Java中的用途非常广泛,以下是一些主要的用途:

  1. 动态类加载

    • 可以在运行时加载和实例化类,而不需要在编译时确定类的确切类型。这对于插件架构和动态模块加载非常有用。
  2. 获取类的信息

    • 通过反射,可以获取类的名称、父类、接口、构造函数、方法和字段等信息,这对于调试和开发工具的实现非常重要。
  3. 动态方法调用

    • 可以在运行时调用对象的方法,而不需要在编译时知道方法名。这使得可以实现更加灵活的代码,比如根据用户输入或配置文件调用不同的方法。
  4. 访问和修改属性

    • 可以访问和修改对象的私有字段,例如进行测试时需要操作私有属性的情况。
  5. 实现通用库和框架

    • 许多Java框架(如Spring、Hibernate)使用反射来实现依赖注入、AOP(面向切面编程)、ORM(对象关系映射)等功能,使得框架能够对用户的应用程序进行灵活处理。
  6. 对象序列化与反序列化

    • 反射可以用于将对象转换为字节流或从字节流恢复对象,常用于对象的持久化和网络传输。
  7. 单元测试和Mock对象

    • 在单元测试中,可以使用反射来创建Mock对象,或访问被测试对象的私有方法和属性,进行更全面的测试。

反射提供了灵活性和可扩展性,但使用时也要注意其性能开销和对程序安全性的影响。

反射相关的类

在Java中,反射相关的类主要集中在 java.lang.reflect 包中,以下是一些常用的反射相关类:

  1. Class

    • 代表一个类或接口的对象。可以用它来获取类的信息,包括类的名称、父类、实现的接口、字段、方法和构造方法等。
  2. Method

    • 表示类中的某个方法。可以通过 Method 类调用该方法,获取方法的参数类型、返回值类型等信息。
  3. Field

    • 表示类中的某个字段(属性)。可以用它来获取字段的类型、访问修饰符,并可以通过反射访问或修改字段的值。
  4. Constructor

    • 表示类的构造函数。可以通过 Constructor 类创建新的对象实例,并获取构造函数的参数类型、修饰符等信息。
  5. Array

    • 提供了对数组的静态方法,可以动态地创建和访问数组。
  6. AccessibleObject

    • 是 FieldMethod 和 Constructor 的父类,包含了一个用于设置访问权限的方法 setAccessible(boolean flag),可以通过它来访问私有成员。
  7. InvocationTargetException

    • 当通过反射调用方法时,如果被调用的方法抛出异常,将会封装在这个异常中。

这些类提供了强大的能力,使得开发者能够在运行时动态地操作类和对象,从而实现灵活和可扩展的代码设计。在使用反射时,需要注意性能开销和安全性问题。

反射的一些相关类的方法

1. Class 类的方法

  • getName():返回类的完全限定名(包括包名)。
  • getSuperclass():返回此 Class 对象所表示的类的父类的 Class 对象。
  • getInterfaces():返回一个 Class 对象数组,表示所实现的接口。
  • getDeclaredMethods():返回一个 Method 对象数组,表示此类声明的所有方法(包括私有方法)。
  • getDeclaredFields():返回一个 Field 对象数组,表示此类声明的所有字段(包括私有字段)。
  • getDeclaredConstructors():返回一个 Constructor 对象数组,表示此类声明的所有构造函数。

2. Method 类的方法

  • getName():返回方法的名称。
  • getReturnType():返回方法的返回类型。
  • getParameterTypes():返回一个 Class 对象数组,表示方法的参数类型。
  • invoke(Object obj, Object... args):在指定对象上调用此 Method 对象表示的原始方法。
  • setAccessible(boolean flag):设置此方法是否可以通过反射访问(包括私有方法)。

3. Field 类的方法

  • getName():返回字段的名称。
  • getType():返回字段的类型(Class 对象)。
  • get(Object obj):返回指定对象上此 Field 对象表示的字段的值。
  • set(Object obj, Object value):为指定对象上此 Field 对象表示的字段设置值。
  • setAccessible(boolean flag):设置此字段是否可以通过反射访问(包括私有字段)。

4. Constructor 类的方法

  • getName():返回构造函数的名称。
  • getParameterTypes():返回一个 Class 对象数组,表示构造函数的参数类型。
  • newInstance(Object... initargs):用构造函数创建新对象实例。

5. Array 类的方法

  • newInstance(Class<?> componentType, int... dimensions):创建一个指定组件类型和维度的新数组。
  • get(Object array, int index):返回数组中指定索引处的值。
  • set(Object array, int index, Object value):设置数组中指定索引处的值。

6. AccessibleObject 类的方法

  • setAccessible(boolean flag):设置此对象是否可被反射访问(如私有成员)。

这些方法使得Java反射能够处理类和对象的多种操作,增强了程序的灵活性和动态性。在使用时,请注意性能和安全性。

反射的使用

下面是一个简单的示例,演示如何使用反射来获取一个类的信息,并调用其方法。

假设我们有一个简单的类 Person,包含一些属性和一个方法:

// Person.java
public class Person {private String name;private int age;public Person(String name, int age) {this.name = name;this.age = age;}public void introduce() {System.out.println("Hello, my name is " + name + " and I am " + age + " years old.");}// Getter和Setter方法public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}
}

以下是使用反射来访问 Person 类的代码:

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Field;public class ReflectionExample {public static void main(String[] args) {try {// 获取Person类的Class对象Class<?> personClass = Class.forName("Person");// 获取构造函数并创建实例Constructor<?> constructor = personClass.getConstructor(String.class, int.class);Object personInstance = constructor.newInstance("Alice", 30);// 获取并调用introduce方法Method introduceMethod = personClass.getMethod("introduce");introduceMethod.invoke(personInstance);// 获取并修改私有字段nameField nameField = personClass.getDeclaredField("name");nameField.setAccessible(true); // 允许访问私有字段nameField.set(personInstance, "Bob"); // 修改字段值// 再次调用introduce方法introduceMethod.invoke(personInstance);} catch (Exception e) {e.printStackTrace();}}
}

代码解释:

  1. 使用 Class.forName 获取 Person 类的 Class 对象。
  2. 通过 getConstructor 方法获取带有参数的构造函数,并使用 newInstance 方法创建 Person 类的一个实例。
  3. 使用 getMethod 获取 introduce 方法,并通过 invoke 调用该方法。
  4. 使用 getDeclaredField 获取私有字段 name,并通过 setAccessible(true) 允许访问私有字段,接着修改它的值。
  5. 再次调用 introduce 方法,输出修改后的结果。

这个示例展示了如何通过反射访问和操作类的属性和方法。

反射优点和缺点

优点:

  • 1. 对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法
  • 2. 增加程序的灵活性和扩展性,降低耦合性,提高自适应能力
  • 3. 反射已经运用在了很多流行框架如:Struts、Hibernate、Spring 等等。

缺点:

  • 1.使用反射会有效率问题。会导致程序效率降低。具体参考这里:大家都说 Java 反射效率低,你知道原因在哪里么_慕课手记
  • 2. 反射技术绕过了源代码的技术,因而会带来维护问题。反射代码比相应的直接代码更复杂 

相关文章:

了解Java中的反射,带你如何使用反射

反射的定义 反射&#xff08;Reflection&#xff09;是Java的一种强大机制&#xff0c;它允许程序在运行时动态地查询和操作类的属性和方法。通过反射&#xff0c;Java程序可以获取类的信息&#xff0c;比如类的名称、方法、字段&#xff0c;以及可以动态地创建对象、调用方法…...

【c++】基础知识——快速入门c++

&#x1f31f;&#x1f31f;作者主页&#xff1a;ephemerals__ &#x1f31f;&#x1f31f;所属专栏&#xff1a;C 目录 前言 一、手搓一个Hello World 二、命名空间namespace 1.命名空间的定义 2.命名空间的使用 3.命名空间补充知识 三、c中的输入和输出 四、缺省参…...

AI学习记录 - 自注意力机制的计算流程图

过段时间解释一下&#xff0c;为啥这样子计算&#xff0c;研究这个自注意力花了不少时间&#xff0c;网上很多讲概念&#xff0c;但是没有具体的流程图和计算方式总结…...

JavaScript快速入门,满满干货总结,快速掌握JS语法,DOM,BOM,事件

目录 一. JavaScript、HTML、CSS简介 1.1 HTML简介和举例说明 1.2 CSS简介和举例说明 1.3 JavaScript 简介和举例说明 二. JavaScript 基本语法 2.1 变量类型和定义方式 2.2 逻辑运算符&#xff0c;比较运算符 2.3 流程控制&#xff0c;if&#xff0c;if...else...&…...

【C++】C++入门基础【类与对象】

目录 1.类 1.1类的定义 1.2struct 与 class对比 2.访问限定符 3. 类域 4.实例化 5.存储大小----内存对齐 6.this指针 1.类 1.1类的定义 class作为类的关键字&#xff0c;后面跟的是类的名字&#xff0c;如Stack&#xff0c;{}中的为类的主体&#xff0c;类定义结束时…...

Qt | QScatterSeries 散点图

点击上方"蓝字"关注我们 01、QScatterSeries QScatterSeries 的类,它将代表散点图中的一个系列。这个类将包含数据点、颜色和样式等属性,以及用于绘制散点图的方法。 02、main.cpp #include <QtWidgets/QApplication>#include <QtWidgets/QMainWindow…...

无缝协作的艺术:Codigger 视频会议(Meeting)的用户体验

在当今数字化的时代&#xff0c;远程协作已经成为工作和学习中不可或缺的一部分。然而&#xff0c;远程协作也面临着诸多挑战&#xff0c;如沟通不畅、信息同步不及时、协作工具的复杂性等。而 Codigger 视频会议&#xff08;Meeting&#xff09;作为一款创新的工具&#xff0c…...

C基础练习(学生管理系统)

1.系统运行&#xff0c;打开如下界面。列出系统帮助菜单&#xff08;即命令菜单&#xff09;&#xff0c;提示输入命令 2.开始时还没有录入成绩&#xff0c;所以输入命令 L 也无法列出成绩。应提示“成绩表为空&#xff01;请先使用命令 T 录入学生成绩。” 同理&#xff0c;当…...

网络安全抓包封包WEB

目录 1.抓包 1. 网络故障排除 应用 意义 2. 网络安全监控 应用 意义 3. 性能优化 应用 意义 4. 协议分析与开发 应用 意义 5. 数据分析与合规性审计 应用 意义 抓包工具 总结 2.抓包的应用对象 1. 网络设备 路由器和交换机 防火墙和入侵检测系统&#xff…...

Spring Boot - 在Spring Boot中实现灵活的API版本控制(上)

文章目录 为什么需要多版本管理&#xff1f;在Spring Boot中实现多版本API的常用方法1. URL路径中包含版本号2. 请求头中包含版本号3. 自定义注解和拦截器 注意事项 为什么需要多版本管理&#xff1f; API接口的多版本管理在我们日常的开发中很重要&#xff0c;特别是当API需要…...

普中51单片机:DS18B20温度传感器操作指南(十三)

文章目录 引言电路图引脚讲解初始化时序写时序读时序温度变换温度读取完整代码 引言 DS18B20是一款单总线接口的数字温度传感器&#xff0c;仅需一个IO口即可实现数据通信。这里只对如何简单操作开发板的DS1802进行讲解&#xff0c;关于DS18B20温度传感器的详细操作原理&#…...

【网络】网络的发展历程及其相关概念

1.什么是网络 计算机网络是指将一群具有独立功能的计算机通过通信设备以及传输媒体被互联起来的&#xff0c;在通信软件的支持下&#xff0c;实现计算机间资源共享、信息交换或协同工作的系统。计算机网络是计算机技术与通信技术紧密结合的产物&#xff0c;两者的迅速发展渗透形…...

鸿蒙HarmonyOS开发:如何使用第三方库,加速应用开发

文章目录 一、如何安装 ohpm-cli二、如何安装三方库1、在 oh-package.json5 文件中声明三方库&#xff0c;以 ohos/crypto-js 为例&#xff1a;2、安装指定名称 pacakge_name 的三方库&#xff0c;执行以下命令&#xff0c;将自动在当前目录下的 oh-package.json5 文件中自动添…...

C++的标准模板库简单介绍

C的标准模板库&#xff08;STL, Standard Template Library&#xff09;是一个强大的工具&#xff0c;旨在提供高效和灵活的数据结构和算法。STL的设计目的是使C程序更加通用和可重用。以下是对STL的详细介绍&#xff1a; 1. STL的组成部分 STL主要由以下几部分组成&#xff…...

安卓常用控件ListView

文章目录 ListView的常用属性ListView的常用APIListView的简单使用 ListView是一个列表样式的 ViewGroup&#xff0c;将若干 item 按行排列。它是一个很基本的控件也是 Android 中最重要的控件之一。它可以实现多个 View 的垂直排列并支持滚动显示效果。 ListView的常用属性 常…...

优秀的行为验证码的应用场景与行业案例

应用场景 登录注册 &#xff1a; 验证码适用于App、Web及小程序等用户注册场景&#xff0c;可以抵御自动机恶意注册&#xff0c;垃圾注册、抵御撞库登录、暴力破解、验证账号敏感信息的修改&#xff0c;同时可以有效阻止撞库攻击&#xff0c;从源头进行防护&#xff0c;保障正…...

《程序猿入职必会(10) · SpringBoot3 整合 MyBatis-Plus》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; CSDN入驻不久&#xff0c;希望大家多多支持&#xff0c;后续会继续提升文章质量&#xff0c;绝不滥竽充数…...

计算机网络408考研 2018

1 计算机网络408考研2018年真题解析_哔哩哔哩_bilibili...

(亲测有效)SpringBoot+Vue项目云服务器部署(宝塔)

目录 一、准备工作 1、购买云服务器 2、获取面板地址 二、jdk和数据库 1、安装环境 2、安装Java环境jdk 3、添加数据库 三、前端部署 1、修改后台服务所在源 2、vue build 2、创建站点 四、后端部署 1、修改application.yml 2、idea打包 3、运行jar包 方式一&a…...

健康管理系统

目录 第1章 系统概述 第2章 可行性研究 2.1 项目背景及意义 2.2 可行性研究 第3章 需求分析 3.1 功能性需求 3.2 非功能性需求 3.2.1 性能需求 第4章 总体设计 4.1 技术架构 4.2功能模块设计 第5章 详细设计 5.1 主页 5.2 写剧本杀 5.3 剧本杀分类管理 5.4 个人…...

浅谈 React Hooks

React Hooks 是 React 16.8 引入的一组 API&#xff0c;用于在函数组件中使用 state 和其他 React 特性&#xff08;例如生命周期方法、context 等&#xff09;。Hooks 通过简洁的函数接口&#xff0c;解决了状态与 UI 的高度解耦&#xff0c;通过函数式编程范式实现更灵活 Rea…...

JavaScript 中的 ES|QL:利用 Apache Arrow 工具

作者&#xff1a;来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗&#xff1f;了解下一期 Elasticsearch Engineer 培训的时间吧&#xff01; Elasticsearch 拥有众多新功能&#xff0c;助你为自己…...

蓝桥杯 2024 15届国赛 A组 儿童节快乐

P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡&#xff0c;轻快的音乐在耳边持续回荡&#xff0c;小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下&#xff0c;六一来了。 今天是六一儿童节&#xff0c;小蓝老师为了让大家在节…...

【HTTP三个基础问题】

面试官您好&#xff01;HTTP是超文本传输协议&#xff0c;是互联网上客户端和服务器之间传输超文本数据&#xff08;比如文字、图片、音频、视频等&#xff09;的核心协议&#xff0c;当前互联网应用最广泛的版本是HTTP1.1&#xff0c;它基于经典的C/S模型&#xff0c;也就是客…...

安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)

船舶制造装配管理现状&#xff1a;装配工作依赖人工经验&#xff0c;装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书&#xff0c;但在实际执行中&#xff0c;工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...

rknn toolkit2搭建和推理

安装Miniconda Miniconda - Anaconda Miniconda 选择一个 新的 版本 &#xff0c;不用和RKNN的python版本保持一致 使用 ./xxx.sh进行安装 下面配置一下载源 # 清华大学源&#xff08;最常用&#xff09; conda config --add channels https://mirrors.tuna.tsinghua.edu.cn…...

【Java多线程从青铜到王者】单例设计模式(八)

wait和sleep的区别 我们的wait也是提供了一个还有超时时间的版本&#xff0c;sleep也是可以指定时间的&#xff0c;也就是说时间一到就会解除阻塞&#xff0c;继续执行 wait和sleep都能被提前唤醒(虽然时间还没有到也可以提前唤醒)&#xff0c;wait能被notify提前唤醒&#xf…...

【Redis】Redis从入门到实战:全面指南

Redis从入门到实战:全面指南 一、Redis简介 Redis(Remote Dictionary Server)是一个开源的、基于内存的键值存储系统,它可以用作数据库、缓存和消息代理。由Salvatore Sanfilippo于2009年开发,因其高性能、丰富的数据结构和广泛的语言支持而广受欢迎。 Redis核心特点:…...

CentOS 7.9安装Nginx1.24.0时报 checking for LuaJIT 2.x ... not found

Nginx1.24编译时&#xff0c;报LuaJIT2.x错误&#xff0c; configuring additional modules adding module in /www/server/nginx/src/ngx_devel_kit ngx_devel_kit was configured adding module in /www/server/nginx/src/lua_nginx_module checking for LuaJIT 2.x ... not…...

DL00871-基于深度学习YOLOv11的盲人障碍物目标检测含完整数据集

基于深度学习YOLOv11的盲人障碍物目标检测&#xff1a;开启盲人出行新纪元 在全球范围内&#xff0c;盲人及视觉障碍者的出行问题一直是社会关注的重点。尽管技术不断进步&#xff0c;许多城市的无障碍设施依然未能满足盲人出行的实际需求。尤其是在复杂的城市环境中&#xff…...