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

Java——反射

目录

5 反射


5 反射

  • 类信息:方法、变量、构造器、继承和实现的类或接口。
  • 反射:反射是 Java 中一项强大的特性,它赋予了程序在运行时动态获取类的信息,并能够调用类的方法、访问类的字段以及操作构造函数等的能力。通过反射,我们可以突破编译期的限制,在运行时对类进行灵活的操作。
  • 获取类信息的前提:生成类对象
  • 类的生命周期与反射关联:

在 Java 中,类的生命周期有着明确的阶段。首先,我们编写的.java源文件通过javac命令进行编译,生成.class字节码文件。之后,类加载器会将.class文件加载到内存中,在元空间(Java 虚拟机专门为存储类的元数据等开辟的内存空间 )中生成类对象。而反射机制的前提就是生成类对象,只有获得了类对象,我们才能进一步获取类的详细信息。

  • 元空间:内存专门为Java开辟的空间。

  • 反射获取类信息的方式

从类对象出发,我们可以从多个维度获取类的信息:

变量相关:

  1. getDeclaredFields() :该方法能够获取类中所有权限修饰的成员变量,包括私有、受保护、包访问以及公共变量。
  2. getDeclaredField(name) :根据指定的变量名获取对应的成员变量,同样不受访问权限限制。
  3. getFields() :用于获取类中所有具有公共访问权限的成员变量。
  4. getField(name) :根据指定名称获取类中具有公共访问权限的成员变量。

对于私有变量,如果要进行访问和操作,需要通过 setAccessible(true) 进行暴力反射,绕过访问权限修饰符的安全检查,之后便可以利用 set() 方法设置变量值,利用 get() 方法获取变量值 。

方法相关:

  1. getDeclaredMethods() :可以获取类中所有权限修饰的成员方法。
  2. getDeclaredMethod(name) :根据指定的方法名获取对应的成员方法。
  3. getMethods() :获取类中所有具有公共访问权限的成员方法。
  4. getMethod(name) :根据指定名称获取类中具有公共访问权限的成员方法。

对于私有方法,同样先使用 setAccessible(true) 进行暴力反射,然后通过 invoke() 方法执行方法,也可以使用 getName() 方法获取方法名。


构造方法相关:

  1. getDeclaredConstructors() :获取类中所有权限修饰的构造方法。
  2. getDeclaredConstructor() :获取指定的无参构造方法。
  3. getDeclaredConstructor(xx.class) :获取指定参数类型的有参构造方法。
  4. getConstructors() :获取类中所有具有公共访问权限的构造方法。

对于私有构造方法,使用 setAccessible(true) 进行暴力反射后,可利用构造方法创建对象,例如通过 newInstance() 方法。如果类有无参构造方法,还可以通过类对象直接调用 class3.newInstance() 来创建实例。


获取类名称的方法
通过反射,还可以获取类的名称。getName() 方法会返回类的全限定名(包名 + 类名 ),而 getSimpleName() 方法则只返回类名本身。

  • 实例代码

如下,一共有两个版本,一个是按照上面的思路,先生成类对象,在从变量、方法构造方法的角度分别解释。第二个版本则是按照反射获取类信息的步骤,按照周一步一步来。

  • 第一个版本:
package com.qcby.反射;public class Person {private String name;private int age;public String country;public int height;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;}public Person(String name, int age, String country, int height) {super();this.name = name;this.age = age;this.country = country;this.height = height;}public Person(String name, int age) {super();this.name = name;this.age = age;}public Person() {super();}private Person(String country) {super();this.country = country;}private void run() {System.out.println("跑跑跑...");}@Overridepublic String toString() {return "Person [name=" + name + ", age=" + age + ", country=" + country + ", height=" + height + "]";}}
package com.qcby.反射;import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;public class Test {public static void main(String[] args) throws Exception {//创建对象Person person1 = new Person();Person person2 = new Person("李四",30,"中国",170);Person person3 = new Person("cici",35,"美国",160);//反射类里面获取类信息的步骤//第一步获取 类对象 //对象阶段获取类对象  对象名.getClass()Person person = new Person();Class class1 = person.getClass();//元空间阶段获取类对象 类名.classClass class2 = Person.class;//硬盘阶段获取类对象 Class.forName(类全名)   包名+类名Class class3 =  Class.forName("com.qcby.反射.Person");System.out.println(class1);//com.qcby.反射.PersonSystem.out.println(class2);//com.qcby.反射.PersonSystem.out.println(class3);//com.qcby.反射.PersonSystem.out.println(class1==class2);//true,因为同一个类在类加载器加载文件的时候,只会执行一次。true也说明了他们同时指向同一个内存空间。System.out.println(class1==class3);//true//第二步  通过类对象 获取类信息//类信息存储的形式一般有两种,所以对于获取可以直接获取或者获取相关的集合		//获取变量System.out.println("========所有访问权限的变量==========");Field[] fields =  class3.getDeclaredFields();for(Field a:fields) {System.out.println(a);}System.out.println("======指定变量============");Field height =  class3.getDeclaredField("height");Field name =  class3.getDeclaredField("name");Field country =  class3.getDeclaredField("country");Field age =  class3.getDeclaredField("age");System.out.println(age);System.out.println("======公共访问权限变量============");Field[] fields1 = class3.getFields();for(Field a:fields1) {System.out.println(a);}System.out.println("======指定公共访问权限变量============");	Field height1 = class3.getField("height");//只可以获取public类型的变量,private不可以//拿到变量后就可以设置值、获取值,如果变量是private权限,直接使用会抛出异常,需要先暴力反射//通过set()和get()设置和获取值//设置值height.set(person1, 180);//name是private,如果通过这种方式会抛出异常,need先暴力反射name.setAccessible(true);//暴力反射,忽略访问权限修饰符的安全检查age.setAccessible(true);//暴力反射name.set(person1, "张三");System.out.println(person1);//获取值System.out.println(height.get(person2));System.out.println(name.get(person2));System.out.println(age.get(person2));System.out.println(country.get(person2));//获取方法System.out.println("=========所有访问权限的方法==================");Method[] methods = class3.getDeclaredMethods();for(Method a:methods) {System.out.println(a);}System.out.println("=========所有指定的方法==================");Method run_method = class3.getDeclaredMethod("run");System.out.println(run_method);Method getName_method = class3.getDeclaredMethod("getName");System.out.println(getName_method);Method setAge_method = class3.getDeclaredMethod("setAge",int.class);//前面获取的方法无形参可以直接用函数名,但是setAge有形参,需要传参数,不然会抛出异常System.out.println(setAge_method);System.out.println("=========公共访问权限的方法==================");Method[] methods1 = class3.getMethods();for(Method a:methods1) {System.out.println(a);}System.out.println("=========指定公共访问权限的方法==================");Method getName_method1 = class3.getMethod("getName");System.out.println(getName_method1);Method setAge_method1 = class3.getMethod("setAge",int.class);System.out.println(setAge_method1);//拿到方法后就可以执行方法Object name = getName_method.invoke(person3);System.out.println(name);setAge_method.invoke(person3, 50);//有行参的要传参System.out.println(person3);run_method.setAccessible(true);//private修饰的方法,要先暴力反射run_method.invoke(person2);System.out.println(run_method.getName());//获取方法名字,如果不知道方法名字要先获取,知道就可以直接获取方法//获取构造方法System.out.println("============获取所有构造方法==============");Constructor[] constructors  =class3.getDeclaredConstructors();for(Constructor a:constructors) {System.out.println(a);}System.out.println("============获取无参构造方法==============");Constructor no_parameter = class3.getDeclaredConstructor();System.out.println(no_parameter);System.out.println("============获取有参构造方法==============");Constructor have_two_parameter = class3.getDeclaredConstructor(String.class,int.class);System.out.println(have_two_parameter);Constructor have_one_parameter = class3.getDeclaredConstructor(String.class);System.out.println(have_one_parameter);System.out.println("============获取公共的构造方法==============");Constructor[] constructors1  =class3.getConstructors();for(Constructor a:constructors1) {System.out.println(a);}//获取构造方法后就可以创建对象Object person1 = no_parameter.newInstance();System.out.println(person1);Object person2 = have_two_parameter.newInstance("李华",21);System.out.println(person2);have_one_parameter.setAccessible(true);//private修饰的构造方法,需要先暴力反射Object person3 = have_one_parameter.newInstance("美国");System.out.println(person3);//特例,无参构造方法可以通过类对象直接调用Object person4 = class3.newInstance();System.out.println(person4);//获取名称//System.out.println(class3.getName());//获取包名加类名//System.out.println(class3.getSimpleName());//只获取类名}
}
  • 第二个版本
package com.qcby.反射;public class Cat implements Jump,Run{private int age;public String name;protected String color;double height;public Cat(int age,String name,String color,double height) {this.age = age;this.name = name;this.color = color;this.height = height;}private Cat() {}Cat(String color){this.color = color;}public void run(String name,int age,double height) {System.out.println("小猫的名字叫"+name);}public void run(String name) {System.out.println("小猫的名字叫"+name);}private int setAge(int age) {return age;}void fly() {System.out.println("猫不会飞");}
}
package com.qcby.反射;public interface Jump {}
package com.qcby.反射;public interface Run {}

package com.qcby.反射;import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;public class Test2 {public static void main(String[] args) throws Exception{//获取类对象Class clazz = Class.forName("com.qcby.反射.Cat");Class clazz1 = Class.forName("com.qcby.反射.Cat");	Class clazz2 = Cat.class;Cat cat = new Cat("黑色");Class clazz3 = cat.getClass();System.out.println(clazz1==clazz2);System.out.println(clazz2==clazz3);//说明clazz1、clazz2和clazz3指向同一个内存空间System.out.println("---------------");//变量Field[] fields = clazz.getDeclaredFields();System.out.println(Arrays.toString(fields));Field ageFiled = clazz.getDeclaredField("age");System.out.println(ageFiled);Field nameFiled = clazz.getDeclaredField("name");System.out.println(nameFiled);Field colorFiled = clazz.getDeclaredField("color");System.out.println(colorFiled);Field heightFiled = clazz.getDeclaredField("height");System.out.println(heightFiled);Field[] fields1 = clazz.getFields();System.out.println(Arrays.toString(fields1));Field nameFiled1 = clazz.getField("name");System.out.println(nameFiled);//Field ageFiled1 = clazz.getField("age");//System.out.println(ageFiled);System.out.println("----------------");//方法Method[] methods = clazz.getDeclaredMethods();System.out.println(Arrays.toString(methods));Method[] methods1 = clazz.getMethods();System.out.println(Arrays.toString(methods1));Method runMethod1 = clazz.getDeclaredMethod("run", String.class);System.out.println(runMethod1);Method runMethod2 = clazz.getMethod("run",String.class);System.out.println(runMethod2);Method flyMethod1 = clazz.getDeclaredMethod("fly");System.out.println(flyMethod1);System.out.println("---------------");//构造函数Constructor[] constructors = clazz.getConstructors();System.out.println(Arrays.toString(constructors));Constructor[] constructors1 = clazz.getDeclaredConstructors();System.out.println(Arrays.toString(constructors1));Constructor constructor1 = clazz.getDeclaredConstructor();System.out.println(constructor1);Constructor constructor2 = clazz.getDeclaredConstructor(String.class);System.out.println(constructor2);//Constructor constructor3 = clazz.getConstructor();//System.out.println(constructor3);System.out.println("----------");//接口Class[] classes = clazz.getInterfaces();System.out.println(Arrays.toString(classes));//拿到类信息后可以进行相应的操作,如果拿到的信息是private修饰,使用时要先进行暴力反射,否则会抛出异常//拿到构造方法 ->创建对象Constructor c1 = clazz.getDeclaredConstructor(int.class,String.class,String.class,double.class);Cat cat1 = (Cat) c1.newInstance(20,"小黑","黑色",240.5);Constructor c2 = clazz.getDeclaredConstructor();c2.setAccessible(true);//暴力反射Cat cat2 = (Cat) c2.newInstance();Constructor c3 = clazz.getDeclaredConstructor(String.class);Cat cat3 = (Cat) c3.newInstance("白色");//拿到变量 ->赋值和获取ageFiled.setAccessible(true);//暴力反射ageFiled.set(cat1, 88);int age = (int) ageFiled.get(cat1);System.out.println(age);nameFiled.set(cat1, "小花");System.out.println(nameFiled.get(cat1));//拿到方法->使用方法runMethod1.invoke(cat1, "小花");Method method2 = clazz.getDeclaredMethod("setAge", int.class);method2.setAccessible(true);System.out.println(method2.invoke(cat1, 18));}}
  • 总结:

反射获取类信息的步骤:

  1. 生成类对象。
  2. 通过类对象获取类信息。
  3. 拿到类信息后可以进行相应的操作,如果拿到的信息是private修饰,使用时要先进行暴力反射,否则会抛出异常。拿到构造方法后可以创建对象;拿到变量后可以赋值和获取值;拿到方法后可以执行方法。

相关文章:

Java——反射

目录 5 反射 5 反射 类信息:方法、变量、构造器、继承和实现的类或接口。反射:反射是 Java 中一项强大的特性,它赋予了程序在运行时动态获取类的信息,并能够调用类的方法、访问类的字段以及操作构造函数等的能力。通过反射&#…...

本地玩AI绘画 | StableDiffusion安装到绘画

环境须知 Cuda必须安装 不需要安装Python,因为该项目会自动安装Python3.10的虚拟环境 1.下载StableDiffusionWebUI压缩包并解压 下载方式一: 从Github下载https://github.com/AUTOMATIC1111/stable-diffusion-webui 的压缩包,解压后名为…...

C++:书架

【描述】 John最近买了一个书架用来存放奶牛养殖书籍&#xff0c;但书架很快被存满了&#xff0c;只剩最顶层有空余。 John共有N头奶牛(1 ≤ N ≤ 20,000)&#xff0c;每头奶牛有自己的高度Hi(1 ≤ Hi ≤ 10,000)&#xff0c;N头奶牛的总高度为S。书架高度为B(1 ≤ B ≤ S <…...

project从入门到精通(四)

目录 日程表的设置和妙用 为日程表视图添加任务 用日程表视图的好处 ​编辑 查找任务的前置任务和后续任务 方法1&#xff1a;采用复合视图的方式 方法3&#xff1a;关系图法 方法4&#xff1a;通过任务路径的方式检查所选任务的前置任务 前置任务和驱动前置任务的区…...

git项目迁移,包括所有的提交记录和分支 gitlab迁移到gitblit

之前git都是全新项目上传&#xff0c;没有迁移过&#xff0c;因为迁移的话要考虑已有项目上的分支都要迁移过去&#xff0c;提交记录能迁移就好&#xff1b;分支如果按照全新项目上传的方式需要新git手动创建好老git已有分支&#xff0c;在手动一个一个克隆老项目分支代码依次提…...

基于STM32、HAL库的SST26VF064B NOR FLASH存储器驱动应用程序设计

一、简介: SST26VF064B是Microchip公司生产的一款64Mbit(8MB)串行闪存器件,采用SPI接口通信,具有以下特点: 工作电压:2.7-3.6V 最高104MHz时钟频率 统一4KB扇区结构 快速擦除和编程时间 低功耗特性 支持标准SPI、Dual SPI和Quad SPI模式 二、硬件接口: STM32L4引脚SST26V…...

【黑马JavaWeb+AI知识梳理】后端Web基础01 - Maven

Maven Maven核心 Maven概述 定义&#xff1a; Maven是一款用于管理和构建Java项目的工具&#xff0c;是apache旗下的一个开源项目&#xff0c;基于项目对象模型&#xff08;POM&#xff0c;project object model&#xff09;的概念&#xff0c;通过一小段描述信息来管理项目的…...

港大今年开源了哪些SLAM算法?

过去的5个月&#xff0c;香港大学 MaRS 实验室陆续开源了四套面向无人机的在线 SLAM 框架&#xff1a;**FAST-LIVO2 、Point-LIO&#xff08;grid-map 分支&#xff09; 、Voxel-SLAM 、Swarm-LIO2 **。这四套框架覆盖了单机三传感器融合、高带宽高速机动、长时间多级地图优化以…...

Spring框架(1)

Spring框架是Java企业级开发中最受欢迎的框架之一&#xff0c;它通过简化开发流程、降低耦合度&#xff0c;让开发者能够更专注于业务逻辑的实现。本文将带你了解Spring框架的核心概念和基本用法。 一、Spring框架简介 Spring是一个轻量级的开源Java开发框架&#xff0c;由Ro…...

边缘计算:技术概念与应用详解

引言 随着物联网&#xff08;IoT&#xff09;、5G 和人工智能&#xff08;AI&#xff09;的快速发展&#xff0c;传统的云计算架构在处理海量数据和实时计算需求时逐渐显现出瓶颈。边缘计算&#xff08;Edge Computing&#xff09;作为一种新兴的计算范式&#xff0c;通过将计…...

Godot4.3类星露谷游戏开发之【昼夜循环】

千里之行&#xff0c;始于足下 文章目录 零、 笔记一、创造时间二、产生颜色三、搭建测试环境四、测试五、免费开源资产包 零、 笔记 为了让游戏可以拥有白天和黑夜&#xff0c;我们需要像上帝一样&#xff0c;在游戏中创造时间的规则&#xff0c;并在不同的时间点产生不同的颜…...

数据结构每日一题day17(链表)★★★★★

题目描述&#xff1a;假设有两个按元素值递增次排列的线性表&#xff0c;均以单链表形式存储。请编与算法将这两个单链表归并为一个按元素值依次递减排列的单链表,并要求利用原来两个单链表的结点存放归并后的单链表。 算法思想&#xff1a; 1.初始化&#xff1a; 创建一个新…...

深入解析多线程与多进程:从理论到Python实践

一、并发编程的核心概念 1.1 多线程的本质与实现原理 多线程&#xff08;Multithreading&#xff09;是指在一个进程内创建多个执行流&#xff0c;共享同一进程资源&#xff08;如内存空间、文件句柄等&#xff09;的编程模型。其核心特征包括&#xff1a; ​​资源共享​​…...

当当网Top500书籍信息爬取与分析

爬取当当网的Top500书籍信息&#xff0c;并对书籍的评价数量进行排序&#xff0c;然后绘制前十名的条形图&#xff0c;然后对各个出版社出版的书籍数量进行排序&#xff0c;绘制百分比的饼图 # 导入所需的模块 import re # 正则表达式模块&#xff0c;用于提取文本中的特定模…...

Android Framework 记录之二

23、services目录 文件描述class AlarmManagerService extends IAlarmManager.Stub {//定时管理服务public class AppOpsService extends IAppOpsService.Stub { // 程序选项服务public class AppsLaunchFailureReceiver extends BroadcastReceiver { //app启动失败广播class A…...

RabbitMQ 幂等性与消息可靠性保障

一、引言 RabbitMQ 是一个广泛应用于软件开发、数据传输、微服务等领域的高效、可靠的开源消息队列系统1。在分布式系统中&#xff0c;保证消息的可靠传递和幂等性是至关重要的&#xff0c;它能够确保系统在各种复杂情况下的稳定性和数据的准确性。 二、消息可靠性保障 &…...

neo4j图数据库基本概念和向量使用

一.节点 1.新建节点 create (n:GroupProduct {name:都邦高保额团意险,description: "保险产品名称"} ) return n CREATE&#xff1a;Neo4j 的关键字&#xff0c;用于创建新节点或关系。 (n:GroupProduct)&#xff1a; n 是节点的临时别名&#xff08;变量名&#…...

修复笔记:获取 torch._dynamo 的详细日志信息

一、问题描述 在运行项目时&#xff0c;遇到与 torch._dynamo 相关的报错&#xff0c;并且希望获取更详细的日志信息以便于进一步诊断问题。 二、相关环境变量设置 通过设置环境变量&#xff0c;可以获得更详细的日志信息&#xff1a; set TORCH_LOGSdynamo set TORCHDYNAM…...

Windows平台下的Qt发布版程序打包成exe可执行文件(带图标)|Qt|C++

首先先找一个可执行文件的图标 可以去阿里的矢量图库里找 iconfont-阿里巴巴矢量图标库 找到想要的图标下载下来 此时的图标是png格式的&#xff0c;我们要转到icon格式的文件 要使用到一个工具Drop Icons_2.1.1.rar - 蓝奏云 生成icon文件后把icon文件放到你项目的根目录下…...

PDF解析新范式:Free2AI工具实测

在数字化浪潮中,PDF文件已成为企业、政府及个人存储与传递信息的核心载体。然而,PDF内容的提取与处理始终是行业痛点——无论是合同解析、研究报告整理,还是大规模知识库构建,传统方法常面临效率低、成本高、准确率不足等问题。Free2AI基于智能体技术与大模型算力,为PDF内…...

CSS--图片链接垂直居中展示的方法

原文网址&#xff1a;CSS--图片链接垂直居中展示的方法-CSDN博客 简介 本文介绍CSS图片链接垂直居中展示的方法。 图片链接 问题复现 源码 <html xml:lang"cn" lang"cn"><head><meta http-equiv"Content-Type" content&quo…...

聊聊Spring AI autoconfigure模块的拆分

序 本文主要研究一下Spring AI autoconfigure模块的拆分 v1.0.0-M6版本 (base) ➜ spring-ai-spring-boot-autoconfigure git:(v1.0.0-M6) tree -L 9 . ├── pom.xml ├── src │ ├── main │ │ ├── java │ │ │ └── org │ │ │ └…...

【Elastsearch】如何获取已创建的api keys

『这种方法其实无法获取秘钥&#xff0c;只是获取了秘钥的名字等信息』 在Elasticsearch中&#xff0c;可以通过API获取已创建的API密钥&#xff08;API keys&#xff09;。以下是具体步骤和示例&#xff1a; 1.使用GET请求获取API密钥 Elasticsearch提供了GETAPI&#xff0c;用…...

Flutter异步原理-Future

前言 在 Dart 中&#xff0c;谈到异步就离不开 Future。无论是 .then()、还是 await&#xff0c;它们背后运作的都是一个私有实现类&#xff1a;_Future &#xff0c;我们平时使用的 Future 只是一个抽象接口&#xff0c;其真正的实现逻辑由_Future 承担。 class _Future<…...

TRAE 配置blender MCP AI自动3D建模

BlenderMCP - Blender模型上下文协议集成 BlenderMCP通过模型上下文协议(MCP)将Blender连接到Claude AI&#xff0c;允许Claude直接与Blender交互并控制Blender。这种集成实现了即时辅助的3D建模、场景创建和操纵。 1.第一步下载 MCP插件(addon.py):Blender插件&#xff0c;在…...

VUE2课程计划表练习

主要练习数据变量对象 以下是修正后的完整代码&#xff1a; //javascript export default {data() {return {list: [{ id: 1, subject: Vue.js 前端实战开发, content: 学习指令&#xff0c;例如 v-if、v-for、v-model 等, place: 自习室, status: false }// 可以在这里添加更…...

虚拟文件系统

虚拟文件系统&#xff08;Virtual File System&#xff0c;VFS&#xff09;是操作系统内核中的一个抽象层&#xff0c;它为不同的文件系统&#xff08;如ext4、NTFS、FAT32等&#xff09;提供统一的访问接口。通过VFS&#xff0c;用户和应用程序无需关心底层文件系统的具体差异…...

2025年软件工程与数据挖掘国际会议(SEDM 2025)

2025 International Conference on Software Engineering and Data Mining 一、大会信息 会议简称&#xff1a;SEDM 2025 大会地点&#xff1a;中国太原 收录检索&#xff1a;提交Ei Compendex,CPCI,CNKI,Google Scholar等 二、会议简介 2025年软件开发与数据挖掘国际会议于…...

基于大模型预测的足月胎膜早破行阴道分娩全流程研究报告

目录 一、引言 1.1 研究背景与意义 1.2 研究目的与方法 1.3 研究创新点 二、胎膜早破(足月)行阴道分娩概述 2.1 胎膜早破定义与分类 2.2 足月胎膜早破行阴道分娩的现状与挑战 2.3 大模型预测引入的必要性 三、大模型预测原理与技术 3.1 大模型介绍 3.2 数据收集与…...

学习记录:DAY28

DispatcherController 功能完善与接口文档编写 前言 没什么动力说废话了。 今天来完善 DispatcherController 的功能&#xff0c;然后写写接口文档。 日程 早上&#xff1a;本来只有早八&#xff0c;但是早上摸鱼了&#xff0c;罪过罪过。下午&#xff1a;把 DispatcherContro…...