我们平常创建类的实例并调用类中成员需要建立在一个前提下,就是已经知道类名和类中成员的信息,灵活性大大降低。甚至在一些项目中还需要修改源码来满足使用条件,大大降低了操作的灵活性。

Java 反射(Reflection)是 Java 语言的一个重要特性,它允许程序在运行时而不是编译时获取类中成员,并且可以动态地操作这些类的成员。

在讲反射之前,我们先聊一聊反射机制中必不可少的一环:配置文件。我需要提前将我的类名,成员名填写到配置文件中去。这样在调用时就可以直接读取配置文件中的信息。相较于读取普通文件,配置文件的读取和调用更加简单。

一、读取配置文件:

1.创建配置文件:在指定的路径下(通常我放在src目录下,不为别的,就因为路径名简单)创建一个以“.properties”为结尾的File文件(普通的键值对形式)作为配置文件。

2.填写配置文件内容:以“键=值”的形式填写,不必添加空格和引号,调用时通过键的字符串形式调用(后面会举例说明)。

3.创建配置文件对象:首先new一个配置文件的对象,使用load方法将配置文件中的内容读取到配置文件对象中。

load方法提供了两种重载,既可以通过字节流输入,也可以通过字符流输入。推荐使用字节流输入,配置文件通常为全英文形式,字节流输入效率高。

4.获取配置文件中的内容:Properties类提供了一种getProperty(键)方法来获取配置文件中的信息,需要在方法中写入一个键,就会返回一个String类型键对应的值。这个String类型的值就是我们要从配置文件中拿到的值。

Exam我提前在src目录下创建了一个名为“p.properties”的配置文件并提前写好键值对来表示需要需要反射文件的路径、属性和方法。路径表示com.reflectNewEdu包下的名为“reflectEdu”的文件,我需要反射这个文件中的成员。

//配置文件的内容
//路径
className = com.reflectNewEdu.reflectEdu
//属性
ObjName = str
//方法
methodName = printContent
methodName1 = printSome

Exam在reflectEdu文件中需要写一些成员来帮助我们进行实验。

public class reflectEdu {//分别一个public和一个private属性public int num = 123;private String str = "字符串";//方法public void printContent() {System.out.println("输出内容");}private void printSome() {System.out.println("输出一些东西");}
}

Exam创建一个Test类,在Test类中填写main方法具体实现反射:

二、获取类对象(main函数中):

1.首先按照上面的步骤创建配置文件对象,并使用字节流加载配置文件进配置文件对象中。

Properties properties = new Properties();
properties.load(new FileReader("src/p.properties"));

2.为了绕过对象阶段创建类对象,Class.forName(类全名)提供了一种在硬盘阶段获取类中成员的方法。Class.forName(类全名)  的核心作用,是通过类的全限定名,让JVM加载这个类,并返回一个代表该类“模板”的 Class  对象。此时仅完成了“类的加载”,并没有创建任何属于这个类的具体对象,就像拿到了一张“汽车设计图纸”,但还没造出真正能开的汽车。

该方法需要写入一个String类型的类全名,我们通过getProperty(键)方法从配置文件中拿到这个类全名。

Class.forName()方法返回一个Class类型的对象,这是一个类对象。类对象并不是哪个类的实例,但可以通过这个类对象下的方法获取到类中的成员,甚至是获取类的实例。(还是挺抽象的

Class class0 = Class.forName(properties.getProperty("className"));

三、获取类对象中的成员:

一、属性(返回Field类型,需要import java.lang.reflect.Field;):

        1.获取当前类里所有属性:getDeclaredFields(); (返回数组)

        2.通过属性名获取属性:getDeclaredField(属性名);

        3.获取所有公共类型属性:getFields();(返回数组)

        4.获取公共类型中指定的属性:getField(属性名);

        5.设置对象的属性:属性对象.set(对象名,属性值)

        当属性被private修饰无法被调用时,可以使用:类对象名.setAccessible(true); 来进行暴力反射。

二、方法(返回Method类型,需要import java.lang.reflect.Method;):

        1.获取类里所有方法:getDeclaredMethods();(返回数组)

        2.通过方法名获取方法:getDeclaredMethod(方法名);

        3.获取所有公共类型方法:getMethods();(返回数组)

        4.获取公共类型中指定的方法:getMethod(方法名);

        5.运行指定的方法:方法对象.invoke(对象名, 参数); 

        第一个为对象名,第二个为参数名,如果没有参数可以不用输入,允许暴力反射。

三、构造方法(返回Constructor类型,需要import java.lang.reflect.Constructor;):

        1.获取类里所有构造方法:getDeclaredConstructors();(返回数组)

        2.获取指定的无参构造方法:getDeclaredConstructor();

        3.获取指定的带有参数的构造方法(举例:带有String和int类型的两个参数的构造方法):getDeclaredConstructor(String.class,int.class);

        4.获取所有公共类型的构造方法:getConstructors();(返回数组)

        5.获取公共类型中指定的一个方法(有参或无参):getConstructor();

        6.执行无参构造方法:Object 新变量名 = 构造方法对象/类对象名.newInstance(); 相当于Object obj = new (); 

        7.执行有参的构造方法:Object 新变量名 = 构造方法对象.newInstance(参数);

需要注意我标蓝的地方,都需要传入一个类对象,那么如何获取类的实例对象呢?

四、获取类的实例对象:

1.通过构造方法获取:我们已经拿到指向我们需要反射的类的对象了,直接通过getDeclaredConstructor()方法获取一个构造方法(我这里是无参的),再执行构造方法中的newInstance()方法不就行了嘛。

代码:

Constructor con = class0.getConstructor();
Object object = con.newInstance();

注:我们提前无法预测给类起的名字是什么,所以需要用它们共同的父类Object对象来接受。

2.通过类对象获取:对类对象直接使用newInstance()方法,这样无需知道类名,就可以创建类的实例对象啦。

Object object = class0.newInstance();

有了类的实例对象,我们就可以使用上面标蓝的方法了,比如调用类中的方法等。

由此,反射的整个过程就实现完了如果有什么地方不明白的话,可以私信讨论( o >o)/。

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

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

相关文章

消息队列-初识kafka

优缺点 消息队列的优点: 实现系统解耦: :::color5 系统解耦解释 有 MQ 时是 “服务 A 发消息到队列,其他服务从队列拿消息,新增服务接队列就行”;无 MQ 时是 “服务 A 直接调其他服务的接口 / 依赖,新增 / …

实践《数字图像处理》之Canny边缘检测、霍夫变换与主动二值化处理在短线段清除应用中的实践

在最近的图像处理项目中,其中一个环节:图片中大量短线(不是噪声),需要在下一步处理前进行清除。在确定具体实现时,碰到了Canny边缘检测、霍夫变换与主动二值化处理的辩证使用,相关逻辑从图片灰度…

vue3与ue5通信-工具类

工具 ue5-simple.js /*** UE5 通信工具* 两个核心方法:发送消息和接收消息*/// 确保全局对象存在 if (typeof window ! undefined) {window.ue window.ue || {};window.ue.interface window.ue.interface || {}; }/*** 生成 UUID*/ function generateUUID() {retu…

在kotlin中如何使用像java中的static

在 Kotlin 中,没有直接的 static 关键字,但有几种等效的方式来实现 Java 中静态成员的功能: 1. 伴生对象 (Companion Object) - 最常用 class MyClass {companion object {// 静态常量const val STATIC_CONSTANT "constant value"…

如何在 Spring Boot 中指定不同的配置文件?

介绍 Spring Boot 提供了多种方式来管理和加载配置文件,特别是在多环境配置下,比如开发、测试和生产环境。通过指定不同的配置文件,可以灵活地调整应用程序的行为,以适应不同的需求。本文将介绍在 Spring Boot 中如何指定使用不同…

在centOS源码编译方式安装MySQL5.7

一、前言 在生产环境中部署数据库时,很多人会选择直接使用 yum/apt 包管理器 安装 MySQL,这样简单快速,但缺点是版本受限,灵活性不足。对于需要指定版本、启用特定编译参数或优化的场景,源码编译安装 MySQL 就显得非常…

探讨Hyperband 等主要机器学习调优方法的机制和权衡

本篇文章Master Hyperband — An Efficient Hyperparameter Tuning Method in Machine Learning深入探讨了Hyperband这一高效的超参数调优方法。文章的技术亮点在于其结合了多臂老虎机策略和逐次减半算法,能够在大搜索空间中快速剔除表现不佳的配置,从而…

Mysql:InnoDB 关键特性

目录 一、插入缓冲(Change Buffer)→ 快递驿站的 “临时存放区” 二、两次写(Double Write)→ 重要文件的 “备份存档” 三、自适应哈希索引(AHI)→ 图书馆的 “热门书快捷查找区” 四、异步 IO&#x…

STM32-----SPI

SPI简介SCK:和I2C中SCL的时钟线一个作用,都是在高电平拿出数据,在低电平写数据MOSI:主机输出从机输入MISO:主机输入从机输出,只有当对应从机的SS为低电平,从机的MISO引脚才能设置推挽输出,当从机SS为高电平时&#xff…

华为考试:HCIE数通考试难度分析

随着信息技术的飞速发展,网络技术已成为支撑各行各业运转的重要基础,市场对高水平网络技术人才的需求持续增长。HCIE作为华为认证体系中的最高级别认证,代表了网络技术领域的专业顶尖水平。本文将对HCIE数通认证的考试内容、难度及备考策略进…

一些常用的激活函数及绘图

深度网络的一些常用激活函数,并通过matplot绘制出来: import matplotlib.pyplot as plt import numpy as npdef relu(x):return np.maximum(0, x)def leaky_relu(x, alpha0.01):return np.where(x > 0, x, alpha * x)def gelu(x):return 0.5 * x * (1…

AE苹果手机iPhone 17展示动画片头模板 App Promo Phone 17 Pro

专为 App 发布会、电商促销、新品宣传 打造的 iPhone 17 Pro 动画展示 AE 模板。 4K 超清分辨率 26 张可替换照片位,无需第三方插件,拖拽即可输出专业级手机宣传片。 核心亮点 4K 超清:38402160 分辨率,大屏投放与社媒高清压缩无…

基于Python的云原生TodoList Demo 项目,验证云原生核心特性

以下是一个基于 Python 的云原生 TodoList Demo 项目,涵盖 容器化、Kubernetes 编排、CI/CD、可观测性、弹性扩缩容 等核心云原生特性,代码简洁且附详细操作指南,适合入门学习。项目概览 目标:实现一个支持增删改查(CR…

go 日志的分装和使用 Zap + lumberjack

自带的log无法满足 按大小轮转 ,按天数清理旧日志 ,自动压缩 ,限制备份数量 ,防止磁盘写满 ,生产环境推荐 等 使用 Zap lumberjack package mainimport ("go.uber.org/zap""go.uber.org/zap/zapcore&q…

【.Net技术栈梳理】01-核心框架与运行时(CLR)

文章目录1 .NET Runtime(CLR-公共语言运行时)1.1 中间语言 IL1.1.1 从源代码到通用中间语言(IL)1.1.2 运行时加载:CLR登场1.1.3 核心步骤:即时编译 (JIT Compilation)1.1.4 执行与内存管理(GC&a…

Claude Code 平替:OpenAI发布 Codex CLI ,GPT-5 国内直接使用

openai推出的命令行编程工具codex已经可以使用最新 GPT-5 模型,拥有可媲美 Claude Code 的 AI 编码能力。本文将指导你在 Windows 系统上部署原生的 Codex CLI 程序,并接入超低价中转 API,让你在国内直接用上超高性价比的 OpenAI Codex CLI 应…

在VS2022的WPF仿真,为什么在XAML实时预览点击 ce.xaml页面控件,却不会自动跳转到具体代码,这样不方便我修改代码,

在VS2022的WPF仿真,为什么在XAML实时预览点击 WpfApp1\FunctionalModule\08Replace\Replace.xaml页面控件,却不会自动跳转到具体代码,这样不方便我修改代码,

Git Bash 别名

有些常用的指令参数非常多,每次都要输入好多参数,我们可以使用别名。Linux 系统中很多 shell,包括 bash,sh,zsh,dash 和 korn 等,不管哪种 shell 都会有一个 .bashrc 的隐藏文件,它就…

Centos7部署ceph存储

一、准备5台centos7主机 node节点双网卡&#xff08;1个内部检测&#xff0c;1个外部使用&#xff09;node节点都添加新网卡关闭防火墙和上下文都需要添加hosts文件都需要cat > /etc/hosts << EOF > 127.0.0.1 localhost localhost.localdomain localhost4 loca…

2025.9.10总结

今日感悟&#xff1a;刷到00后下班去菜市场捡菜的热点视频&#xff0c;确实挺有意思&#xff0c;不得不说&#xff0c;又省钱又好玩。虽然每天晚上能免费领个25块钱的水果回去&#xff0c;但确实没有什么新鲜感了。别人下班还能捡捡菜放松下&#xff0c;我下班&#xff0c;除了…