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

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 的反射&#xff08;reflection&a…...

【Qt QML入门】Image

Image类型显示一个图像。 使用source属性将图像的源指定为URL。图像可以以Qt支持的任何标准图像格式提供&#xff0c;包括位图格式&#xff0c;如PNG和JPEG&#xff0c;以及矢量图形格式&#xff0c;如SVG。 如果没有指定宽度和高度属性&#xff0c;图像将自动使用加载图像的大…...

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 装置传输的注意事项

来源&#xff1a;大大通 作者&#xff1a;冷氣團 1 USB Bulk 是什么 USB 是即插即用使用差动信号的装置界面&#xff0c;是以 端点 ( Endpoint )&#xff0c;做为传输装置的输出入端&#xff0c;透过不同的端点 ( Endpoint ) 和模式&#xff0c;来进行与装置的沟通&#xff…...

c语言结构体调用格式与对齐

1.声明形式&#xff1a; struct 结构体名字 { 结构体成员 }结构体变量名&#xff1b; 2.赋值方法 3.结构体对齐&#xff1a; 1.起始偏移量&#xff1a;默认结构体第一个元素对齐0起始偏移量&#xff0c;第一个元素占一个字节&#xff0c;此时偏移量为1. 2.标准数&#xff…...

服务器常用命令介绍和负载监控的工具插件推荐

先赞后看&#xff0c;养成习惯&#xff01;&#xff01;&#xff01;❤️ ❤️ ❤️ 码字不易&#xff0c;如果喜欢可以关注我哦&#xff01; 如果本篇文章对你有所启发&#xff0c;欢迎访问我的个人博客 命令 服务器相关 5个常用命令 top Top命令不仅显示了当前内核服务的…...

linux 防火墙systemctl (个人笔记)

查看 systemctl status firewalld 开启 systemctl start firewalld 关闭 systemctl stop firewalld.service 查看所有 firewall-cmd --zonepublic --list-ports 开放端口&#xff1a;// --permanent 永久生效,没有此参数重启后失效 firewall-cmd --zonepublic --add-port9527/…...

处理器中store指令的处理

对于向存储器中保存数据的store指令来说,它在顺利离开流水线之前是不允许改变处理器状态的&#xff0c;只有等到它退休(retire)的时候&#xff0c;才允许将它携带的数据写到D-Cache中在此之前&#xff0c;store指令即使计算完毕&#xff0c;也会将结果暂存在一个缓存中&#xf…...

杨辉三角形-第11届蓝桥杯选拔赛Python真题精选

[导读]&#xff1a;超平老师的Scratch蓝桥杯真题解读系列在推出之后&#xff0c;受到了广大老师和家长的好评&#xff0c;非常感谢各位的认可和厚爱。作为回馈&#xff0c;超平老师计划推出《Python蓝桥杯真题解析100讲》&#xff0c;这是解读系列的第17讲。 杨辉三角形&#…...

我们一起做过的SPA——Nuxt.js介绍

Nuxt.js 1 我们一起做过的SPA SPA&#xff08;single page web application&#xff09;单页 Web 应用&#xff0c;Web 不再是一张张页面&#xff0c;而是一个整体的应用&#xff0c;一个由路由系统、数据系统、页面&#xff08;组件&#xff09;系统等等&#xff0c;组成的应…...

java导出word使用模版与自定义联合出击解决复杂表格!

1. 看一下需要导出什么样子的表格 如图所示&#xff0c;这里的所有数据行都是动态的&#xff0c;需要根据查询出来的数据循环展示。 如果只是这样的话&#xff0c;使用freemarker应该都可以搞定&#xff0c;但是他一列中内容相同的单元格&#xff0c;需要合并。 这对于表格样式…...

GO设计模式——9、过滤器模式(结构型)

目录 过滤器模式&#xff08;Filter/Criteria Pattern&#xff09; 代码实现 过滤器模式&#xff08;Filter/Criteria Pattern&#xff09; 过滤器模式&#xff08;Filter Pattern&#xff09;或标准模式&#xff08;Criteria Pattern&#xff09;是一种设计模式&#xff0c;…...

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串口通讯

一、串行通讯接口 串行通讯接口简称串口&#xff08;UART&#xff09; 采用串行通信方式的扩展接口&#xff0c;数据位一位一位的按照顺序传送 优点&#xff1a;通信线路简单&#xff0c;只要一对传输线就可以实现双向通信能够大大降低成本&#xff0c;适合远距离通信。 缺点…...

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-爬取壁纸

代理池的&#xff0c;防止IP 被封 找到图片真实地址 现在看到的只是图片的预览地址 (previews) 1.检查&#xff1a; 2.鼠标变为箭头时查看网页源代码 关于怎样在源代码中找到图片的真实地址 ??? 为什么在源代码界面 ctrl f 时候搜索的是 .png ??? 首先图片地址是以 .j…...

第31期 | GPTSecurity周报

GPTSecurity是一个涵盖了前沿学术研究和实践经验分享的社区&#xff0c;集成了生成预训练Transformer&#xff08;GPT&#xff09;、人工智能生成内容&#xff08;AIGC&#xff09;以及大型语言模型&#xff08;LLM&#xff09;等安全领域应用的知识。在这里&#xff0c;您可以…...

湖仓一体架构理论与实践汇总

湖仓一体架构理论与实践汇总 软件研发本质上属于“手工业”。软件研发在很大程度上还是依赖于个人的能力。当软件规模较小时&#xff0c;依赖“手工业”可以解决问题&#xff0c;但是当软件规模大了之后再依赖“手工业”就不行了。 软件的复杂度包含两个层面&#xff1a;软件…...

Redission从入门到入门

1. Redisson简介 Redisson 是一个在 Java 环境中使用的 Redis 客户端库。它提供了丰富的功能&#xff0c;使得在 Java 应用中与 Redis 交互变得更加简单和高效。Redisson 不仅提供了基本的 Redis 操作&#xff0c;还提供了许多高级功能&#xff0c;使其成为在 Java 项目中实现…...

Linux链表操作全解析

Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表&#xff1f;1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...

Docker 运行 Kafka 带 SASL 认证教程

Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明&#xff1a;server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...

【单片机期末】单片机系统设计

主要内容&#xff1a;系统状态机&#xff0c;系统时基&#xff0c;系统需求分析&#xff0c;系统构建&#xff0c;系统状态流图 一、题目要求 二、绘制系统状态流图 题目&#xff1a;根据上述描述绘制系统状态流图&#xff0c;注明状态转移条件及方向。 三、利用定时器产生时…...

dify打造数据可视化图表

一、概述 在日常工作和学习中&#xff0c;我们经常需要和数据打交道。无论是分析报告、项目展示&#xff0c;还是简单的数据洞察&#xff0c;一个清晰直观的图表&#xff0c;往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server&#xff0c;由蚂蚁集团 AntV 团队…...

初学 pytest 记录

安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...

Python ROS2【机器人中间件框架】 简介

销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...

VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP

编辑-虚拟网络编辑器-更改设置 选择桥接模式&#xff0c;然后找到相应的网卡&#xff08;可以查看自己本机的网络连接&#xff09; windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置&#xff0c;选择刚才配置的桥接模式 静态ip设置&#xff1a; 我用的ubuntu24桌…...

android13 app的触摸问题定位分析流程

一、知识点 一般来说,触摸问题都是app层面出问题,我们可以在ViewRootImpl.java添加log的方式定位;如果是touchableRegion的计算问题,就会相对比较麻烦了,需要通过adb shell dumpsys input > input.log指令,且通过打印堆栈的方式,逐步定位问题,并找到修改方案。 问题…...

日常一水C

多态 言简意赅&#xff1a;就是一个对象面对同一事件时做出的不同反应 而之前的继承中说过&#xff0c;当子类和父类的函数名相同时&#xff0c;会隐藏父类的同名函数转而调用子类的同名函数&#xff0c;如果要调用父类的同名函数&#xff0c;那么就需要对父类进行引用&#…...

什么是VR全景技术

VR全景技术&#xff0c;全称为虚拟现实全景技术&#xff0c;是通过计算机图像模拟生成三维空间中的虚拟世界&#xff0c;使用户能够在该虚拟世界中进行全方位、无死角的观察和交互的技术。VR全景技术模拟人在真实空间中的视觉体验&#xff0c;结合图文、3D、音视频等多媒体元素…...