反射、反射调用以及修改成员变量,成员方法,构造函数、反射的应用

DAY11.2 Java核心基础

反射(第二弹)

第一弹请访问链接:

反射(第一篇)

  • getMethod(String name, Class… parameterTypes)
  • getMethods()
  • getDeclaredMethod(String name,Class… parameterTypes)
  • getDeclaredMethods()

getMethods() 获取类中所有方法,包括从父类继承过来的方法以及自定义的方法,这些方法都是 public 方法

public String getName() {return name;
}private void setName(String name) {this.name = name;
}protected int getAge() {return age;
}void setAge(int age) {this.age = age;
}@Override
public String toString() {return "User{" +"name='" + name + '\'' +", age=" + age +'}';
}
public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException {Class class1 = Class.forName("com.deepSeek.shuwu.Day11.User");Method[] methods = class1.getMethods();for (Method method : methods) {System.out.println(method.getName());}
}

image-20250314114226045

可以看见这个输出只有public访问符的方法

getMethod(String name,Class… parameterTypes) 根据方法名和参数列表获取具体的某个方法,只能是 public

方法,包括自定义的方法以及从父类继承过来的方法

private void setName(String name) {this.name = name;
}
Class class1 = Class.forName("com.deepSeek.shuwu.Day11.User");
Method setName = class1.getMethod("setName", String.class);
System.out.println(setName);

image-20250314114615886

这样是获取不到的,抛出找不到方法的异常

因为这个只能获取到公有方法(public修饰的)

改为public就可以获取到了

image-20250314114717350

同理

getDeclaredMethods() 获取类中所有的方法,包括 public、protected、private、默认,但是无法获取从父类继承过来的方法

public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException {Class class1 = Class.forName("com.deepSeek.shuwu.Day11.User");Method[] declaredMethods = class1.getDeclaredMethods();for (Method declaredMethod : declaredMethods) {System.out.println(declaredMethod.getName());}
}
public String getName() {return name;
}public void setName(String name) {this.name = name;
}protected int getAge() {return age;
}void setAge(int age) {this.age = age;
}@Override
public String toString() {return "User{" +"name='" + name + '\'' +", age=" + age +'}';
}

输出:

image-20250314114947797

可以看见可以获取所有声明的方法,和这个方法的访问权限符无关

getDeclaredMethod(String name,Class… parameterTypes) 根据方法名和参数列表获取具体的某个方法,对于访问权限修饰符没有限制,但是只能获取自定义的方法

Class class1 = Class.forName("com.deepSeek.shuwu.Day11.User");
Method getAge = class1.getDeclaredMethod("getAge");
System.out.println(getAge);

获取到的是protected的方法,对于访问权限修饰符没有限制,但是只能获取自定义的方法

image-20250314115329416

获取类中成员变量

Class 提供了 4 个方法获取类中的成员变量

  • getFields():获取类中全部的 public 修饰的成员变量,包括继承自父类的成员变量以及自定义的成员变量
  • getDeclaredFields():获取类中全部修饰符修饰的成员变量,但仅限于类自定义的,不包括从父类继承过来的
  • getField(String name):根据成员变量名称获取类中的某个具体的 public 修饰的成员变量,包括继承自父类的成员变量以及自定义的成员变量
  • getDeclaredField(String name):根据成员变量名称获取类中某个具体的成员变量,不受访问权限修饰符的限制,但是只能获取类自定义的成员变量,不包括从父类继承过来的成员变量

和上面的获取方法同理

类中的字段:

public String name;
public int age;
private String sex;
Class class1 = Class.forName("com.deepSeek.shuwu.Day11.User");
Field[] fields = class1.getFields();
for (Field field : fields) {System.out.println(field);
}
System.out.println(class1.getDeclaredField("name"));

image-20250314115853375

可以看见getFields()获取到两个public的字段,getDeclaredField获取的是privare的sex

反射就是在程序运行的时候动态获取类的信息(比如构造器,成员方法,成员变量)

反射的应用

通过 Class 类提供的方法可以获取类中的成员变量、成员方法、构造函数

获取这些有什么用?实际开发中如何应用反射?

反射调用方法

常规创建并操作对象的方法

public User(String name, int age, String sex) {this.name = name;this.age = age;this.sex = sex;
}
public String getInfo() {return this.name + " " + this.age + " " + this.sex;
}
User user = new User("deepseek", 18, "男");
user.getInfo();

User类的构造方法和测试方法

getMethod() 和 invoke()

public User(String name, int age, String sex) {this.name = name;this.age = age;this.sex = sex;
}
public String getInfo() {return this.name + " " + this.age + " " + this.sex;
}
Class class1 = Class.forName("com.deepSeek.shuwu.Day11.User");
Constructor constructor = class1.getConstructor(String.class, int.class, String.class);
User user1 = (User) constructor.newInstance("deepSeek", 18, "男");
Method getInfoMethod = class1.getMethod("getInfo",null);
System.out.println(getInfoMethod.invoke(user1));

输出:

image-20250314151315980

反射就是将常规方式进行反转

// 常规调用
user.getInfo();
// 反射创建
Method getInfoMethod = class1.getMethod("getInfo",null);
System.out.println(getInfoMethod.invoke(user1));

常规:

1、创建实例化对象

2、调用实例化对象的方法

反射:

1、获取反射源头 Class 对象

2、根据 Class 对象获取目标方法

3、通过反射机制调用目标方法

反射访问成员变量

getDeclaredFields() :获取类中所有成员变量

Class class1 = Class.forName("com.deepSeek.shuwu.Day11.User");
Field[] declaredFields = class1.getDeclaredFields();
for (Field declaredField : declaredFields) {// 获取字段名称、类型、修饰符、泛型类型System.out.println(declaredField.getName());System.out.println(declaredField.getType());System.out.println(declaredField.getModifiers());System.out.println(declaredField.getGenericType());System.out.println("-------------------------------");
}

image-20250314153500517

获取字段,然后可以传入对象获取对象的id;

public static void main(String[] args) throws Exception {// 加载 User 类Class<?> class1 = Class.forName("com.deepSeek.shuwu.Day11.User");// 创建 User 对象User user1 = new User("user1", 18, "男");User user2 = new User("user2", 18, "男");User user3 = new User("user3", 18, "男");// 获取 name 字段(假设它是 public 的)Field name = class1.getField("name");System.out.println(name.get(user1)); System.out.println(name.get(user2)); System.out.println(name.get(user3)); // 获取 sex 字段(private 字段)Field sex = class1.getDeclaredField("sex");sex.setAccessible(true); System.out.println(sex.get(user1)); // 修改 user1 的 sex 字段值sex.set(user1, "女");System.out.println(sex.get(user1)); 
}

输出:

image-20250314165842249

可以通过反射获取到对象的private值,以及对对象的值进行修改

如下图所示:

image-20250314170801136

反射调用构造函数

反射机制下用 Constructor 类来描述构造函数,同时一个类可以拥有多个构造函数

一个User类中的三个构造函数:

public User(String name, int age, String sex) {this.name = name;this.age = age;this.sex = sex;
}
public User() {}
public User(String name, int age) {this.name = name;this.age = age;
}
@Override
public String toString() {eturn "User{" +"name='" + name + '\'' +", age=" + age +", sex='" + sex + '\'' +'}';
}

测试类;

// 加载 User 类
Class<?> class1 = Class.forName("com.deepSeek.shuwu.Day11.User");Constructor<?> constructor1 = class1.getConstructor(String.class, int.class);
User user1 = (User) constructor1.newInstance("李四", 20);
System.out.println(user1);Constructor<?> constructor2 = class1.getConstructor(null);
User user2 = (User) constructor2.newInstance();
System.out.println(user2);Constructor<?> constructor3 = class1.getConstructor(String.class, int.class, String.class);
User user3 = (User) constructor3.newInstance("张三", 18, "男");
System.out.println(user3);

输出:

image-20250314171428240

反射调用构造函数和反射调用普通方法的区别

1、构造函数使用 Constructor 来表示,普通方法使用 Method 来表示

2、Constructor 调用的是 newInstance 方法,Method 调用的是 invoke 方法

3、Constructor 不需要传入对象,只需传入参数,Method 需要同时传入对象和参数

直接访问成员变量进行赋值 or 通过调用成员方法对成员变量进行赋值

public static void main(String[] args) throws Exception {// 加载 User 类Class<?> class1 = Class.forName("com.deepSeek.shuwu.Day11.User");User user =new User();Field name = class1.getField("name");// 直接赋值name.set(user,"deepSeek");// 如果不是public字段,需要先设置可访问性Field age = class1.getDeclaredField("age");age.setAccessible(true);age.set(user,19);// 调用 setSex 方法赋值,前提是这个方法是publicMethod setSex = class1.getMethod("setSex", String.class);setSex.invoke(user,"女");// 输出System.out.println(user);
}

image-20250314172810633

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

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

相关文章

【鸿蒙开发】Hi3861学习笔记- 外部中断

00. 目录 文章目录 00. 目录01. 概述02. EXTI相关API03. 硬件设计04. 软件设计05. 实验现象06. 附录 01. 概述 我们在做按键控制实验时&#xff0c;虽然能实现 IO 口输入功能&#xff0c;但代码是一直在检测 IO 输入口的变化&#xff0c;因此效率不高&#xff0c;特别是在一些…

使用 crontab 定时同步服务器文件到本地

https://www.dong-blog.fun/post/1987 1. 安装 sshpass sshpass 是一个可以自动输入密码的工具。如果未安装&#xff0c;运行以下命令安装&#xff1a; • 对于 Debian/Ubuntu 系统&#xff1a; apt update && apt install sshpass• 对于 CentOS/RHEL 系统&#xf…

反射机制的理解

一、getName 方法解析 代码功能 public static String getName(String key) throws IOException {Properties properties new Properties();FileInputStream in new FileInputStream("D:\\路径...\\application.properties");properties.load(in); // 加载配置文…

Visual studio + Qt 项目配置管理

Visual studio Qt 项目配置管理 1.本机顺利安装 vs 和 Qt 软件 ​ 并且设置好Qt 的环境变量比如 E:\Qt\Qt5.9.8\5.9.8\msvc2017_64\bin E:\Qt\Qt5.9.8\5.9.8\msvc2017_64\lib E:\Qt\Qt5.9.8\5.9.8\msvc2017_64\include //这里是你电脑上Qt的路径&#xff0c;每台电脑不一样…

通过 Python 爬虫提高股票选股胜率

此贴为Python爬虫技术学习贴 在股票中&#xff0c;即便有了选股规则&#xff0c;从5000多只股票中筛选出符合规则的股票也是十分困难的&#xff0c;于是想通过爬虫来实现自动化的快速选股。全文用GP代替股票 实现方案 1、指定两套规则&#xff0c;第一套弱约束&#xff0c;第…

SpringCloud带你走进微服务的世界

认识微服务 随着互联网行业的发展&#xff0c;对服务的要求也越来越高&#xff0c;服务架构也从单体架构逐渐演变为现在流行的微服务架构。这些架构之间有怎样的差别呢&#xff1f; 单体架构 单体架构&#xff1a;将业务的所有功能集中在一个项目中开发&#xff0c;打成一个…

FastAPI复杂查询终极指南:告别if-else的现代化过滤架构

title: FastAPI复杂查询终极指南:告别if-else的现代化过滤架构 date: 2025/3/14 updated: 2025/3/14 author: cmdragon excerpt: 本文系统讲解FastAPI中复杂查询条件的构建方法,涵盖参数验证、动态过滤、安全防护等18个核心技术点。通过引入策略模式、声明式编程等技术,彻…

Ubuntu 22.04使用pigz多线程快速解压/压缩文件

最近搞项目&#xff0c;资料太大&#xff0c;解压时间太久&#xff0c;于是想办法解决。 开贴记录。 1.安装pigz sudo apt install pigz 2.解压资料 解压命令为 tar --use-compress-programpigz -xvpf ***.tar.gz 将最后的部分***.tar.gz换成你自己的文件即可 例如 ti…

Amazon Quantum Ledger Database (QLDB):革新数据可信记录的终极解决方案

在数字化浪潮中&#xff0c;企业数据的安全性与可信性成为核心挑战。无论是金融交易的透明审计、供应链的全程追踪&#xff0c;还是医疗记录的真实性验证&#xff0c;如何确保数据不可篡改且可追溯&#xff0c;已成为企业亟待解决的难题。Amazon Quantum Ledger Database (QLDB…

日本IT|AWS工作内容及未来性、以及转职的所需资质和技能

AWSとは AWSはAmazon Web Services&#xff08;アマゾンウェブサービス&#xff09;の略称です。 名称から分かるとおり、ネットを通じた通販などを事業として行っているAmazon.com社がクラウドサービスとして運営しています。 本来であれば自分たちでインフラ環境を構築する…

Conda+jupyterlab

文章目录 1、Conda1.1、基本介绍1.2、conda安装1.3、conda常用命令1.3.1、基本命令1.3.2、环境管理 2、Jupyterlab2.1、基本介绍2.2、安装使用 3、pycharm中使用conda 1、Conda 1.1、基本介绍 Conda 是一个开源的包管理和环境管理工具&#xff0c;适用于 Python 及其他编程语…

Vue 项目中 CDN 引入的利弊及解决方案

在Vue项目中&#xff0c;引入到工程中的所有js、css文件&#xff0c;编译时都会被打包进vendor.js&#xff0c;浏览器在加载该文件之后才能开始显示首屏。若是引入的库众多&#xff0c;那么vendor.js文件体积将会相当的大&#xff0c;影响首屏的体验。通过调试发送时间主要消耗…

拥有一台云服务器能做什么呢?

拥有一台云服务器就像拥有了一台24小时在线的远程电脑&#xff0c;你可以通过互联网随时随地管理它。它的用途非常广泛&#xff0c;无论是个人学习、开发测试&#xff0c;还是企业级应用部署&#xff0c;都能发挥重要作用。以下是常见的应用场景&#xff0c;按需求分类整理&…

PHP 在 if 判断时由于运算符优先级导致 false 的问题

首先来看一段代码&#xff1a; $price 187.50;if (!is_numeric($price) || $price < 0 || ($price * 100 > 1000000)) {echo "价格错误&#xff1a;$price\n"; } else {echo "价格正确&#xff1a;$price\n"; }乍一看是不是认为并没有什么问题&…

从零基础到能独立设计单片机产品,一般需要经历哪些学习阶段?

相信很多人&#xff0c;内心都有“钢铁侠”的幻想&#xff0c;成为能写程序&#xff0c;能设计硬件&#xff0c;能设计结构&#xff0c;能焊接的全能型人才。 上次徐工问我&#xff0c;如果你财富自由了&#xff0c;想去做啥&#xff1f; 我说出来&#xff0c;可能大家都不信&a…

Liunx启动kafka并解决kafka时不时挂掉的问题

kafka启动步骤 先启动zookeeper&#xff0c;启动命令如下 nohup ./zookeeper-server-start.sh /home/kafka/kafka/config/zookeeper.properties > /home/kafka/kafka/zookeeper.log 2>&1 &再启动kafka&#xff0c;启动命令如下 nohup ./kafka-server-start.sh…

使用STM32CubeMX配置定时器中断实现LED每秒闪烁一次(STM32G070CBT6)

说明&#xff1a; 本案例采用的定时器3&#xff08;TIM3&#xff09;实现&#xff0c;使用其他定时器是一样配置。 如何新建一个工程以及如何配置LED的端口&#xff0c;请查看前面文章&#xff1a;使用STM32CubeMX实现LED灯每秒闪烁一次&#xff08;STM32G070CBT6单片机&…

暴力破解Excel受保护的单元格密码

暴力破解Excel受保护的单元格密码 分享一个暴力破解Excel受保护的单元格密码的方法 第一步 在Excel中按下Alt F11&#xff0c;打开Visual Basic for Applications&#xff08;VBA&#xff09;编辑器。 第二步 在VBA编辑器中&#xff0c;点击插入菜单&#xff0c;选择模块…

Git常用操作之GitLab

Git常用操作之GitLab 小薛博客官网&#xff1a;小薛博客Git常用操作之GitLab官方地址 1、GitLab安装 https://gitlab.cn/install/ 1、Docker安装GitLab https://docs.gitlab.cn/jh/install/docker.html 1、设置卷位置 在设置其他所有内容之前&#xff0c;请配置一个新的…

pgsql创建新用户并赋只读权限

在 PostgreSQL 中&#xff0c;为新用户赋予只读权限的步骤如下&#xff1a; —### 1. 创建新用户首先&#xff0c;创建一个新用户&#xff08;角色&#xff09;&#xff0c;并设置密码&#xff1a;sqlCREATE ROLE 用户名 WITH LOGIN PASSWORD 密码;例如&#xff1a;sqlCREATE R…