从零开始学习 Java:简单易懂的入门指南之反射(三十八)
反射
- 1. 反射
- 1.1 反射的概述:
- 1.2 学习反射到底学什么?
- 1.3 获取字节码文件对象的三种方式
- 1.4 字节码文件和字节码文件对象
- 1.5 获取构造方法
- 1.6 获取构造方法并创建对象
- 1.7 获取成员变量
- 1.8 获取成员变量并获取值和修改值
- 1.9 获取成员方法
- 1.10 获取成员方法并运行
- 面试题:
1. 反射
1.1 反射的概述:
专业的解释:
是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;
对于任意一个对象,都能够调用它的任意属性和方法;
这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制。
通俗的理解:
-
利用反射创建的对象可以无视修饰符调用类里面的内容
-
可以跟配置文件结合起来使用,把要创建的对象信息和方法写在配置文件中。
读取到什么类,就创建什么类的对象
读取到什么方法,就调用什么方法
此时当需求变更的时候不需要修改代码,只要修改配置文件即可。
1.2 学习反射到底学什么?
反射都是从class字节码文件中获取的内容。
- 如何获取class字节码文件的对象
- 利用反射如何获取构造方法(创建对象)
- 利用反射如何获取成员变量(赋值,获取值)
- 利用反射如何获取成员方法(运行)
1.3 获取字节码文件对象的三种方式
- Class这个类里面的静态方法forName(“全类名”)(最常用)
- 通过class属性获取
- 通过对象获取字节码文件对象
代码示例:
//1.Class这个类里面的静态方法forName
//Class.forName("类的全类名"): 全类名 = 包名 + 类名
Class clazz1 = Class.forName("com.itheima.reflectdemo.Student");
//源代码阶段获取 --- 先把Student加载到内存中,再获取字节码文件的对象
//clazz 就表示Student这个类的字节码文件对象。
//就是当Student.class这个文件加载到内存之后,产生的字节码文件对象//2.通过class属性获取
//类名.class
Class clazz2 = Student.class;//因为class文件在硬盘中是唯一的,所以,当这个文件加载到内存之后产生的对象也是唯一的
System.out.println(clazz1 == clazz2);//true//3.通过Student对象获取字节码文件对象
Student s = new Student();
Class clazz3 = s.getClass();
System.out.println(clazz1 == clazz2);//true
System.out.println(clazz2 == clazz3);//true
1.4 字节码文件和字节码文件对象
java文件:就是我们自己编写的java代码。
字节码文件:就是通过java文件编译之后的class文件(是在硬盘上真实存在的,用眼睛能看到的)
字节码文件对象:当class文件加载到内存之后,虚拟机自动创建出来的对象。
这个对象里面至少包含了:构造方法,成员变量,成员方法。
而我们的反射获取的是什么?字节码文件对象,这个对象在内存中是唯一的。
1.5 获取构造方法
规则:
get表示获取
Declared表示私有
最后的s表示所有,复数形式
如果当前获取到的是私有的,必须要临时修改访问权限,否则无法使用
| 方法名 | 说明 |
|---|---|
| Constructor<?>[] getConstructors() | 获得所有的构造(只能public修饰) |
| Constructor<?>[] getDeclaredConstructors() | 获得所有的构造(包含private修饰) |
| Constructor getConstructor(Class<?>… parameterTypes) | 获取指定构造(只能public修饰) |
| Constructor getDeclaredConstructor(Class<?>… parameterTypes) | 获取指定构造(包含private修饰) |
代码示例:
public class ReflectDemo2 {public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {//1.获得整体(class字节码文件对象)Class clazz = Class.forName("com.itheima.reflectdemo.Student");//2.获取构造方法对象//获取所有构造方法(public)Constructor[] constructors1 = clazz.getConstructors();for (Constructor constructor : constructors1) {System.out.println(constructor);}System.out.println("=======================");//获取所有构造(带私有的)Constructor[] constructors2 = clazz.getDeclaredConstructors();for (Constructor constructor : constructors2) {System.out.println(constructor);}System.out.println("=======================");//获取指定的空参构造Constructor con1 = clazz.getConstructor();System.out.println(con1);Constructor con2 = clazz.getConstructor(String.class,int.class);System.out.println(con2);System.out.println("=======================");//获取指定的构造(所有构造都可以获取到,包括public包括private)Constructor con3 = clazz.getDeclaredConstructor();System.out.println(con3);//了解 System.out.println(con3 == con1);//每一次获取构造方法对象的时候,都会新new一个。Constructor con4 = clazz.getDeclaredConstructor(String.class);System.out.println(con4);}
}
1.6 获取构造方法并创建对象
涉及到的方法:newInstance
代码示例:
//首先要有一个javabean类
public class Student {private String name;private int age;public Student() {}public Student(String name) {this.name = name;}private Student(String name, int age) {this.name = name;this.age = age;}//get,set方法public String toString() {return "Student{name = " + name + ", age = " + age + "}";}
}//测试类中的代码:
//需求1:
//获取空参,并创建对象//1.获取整体的字节码文件对象
Class clazz = Class.forName("com.itheima.a02reflectdemo1.Student");
//2.获取空参的构造方法
Constructor con = clazz.getConstructor();
//3.利用空参构造方法创建对象
Student stu = (Student) con.newInstance();
System.out.println(stu);System.out.println("=============================================");//测试类中的代码:
//需求2:
//获取带参构造,并创建对象
//1.获取整体的字节码文件对象
Class clazz = Class.forName("com.itheima.a02reflectdemo1.Student");
//2.获取有参构造方法
Constructor con = clazz.getDeclaredConstructor(String.class, int.class);
//3.临时修改构造方法的访问权限(暴力反射)
con.setAccessible(true);
//4.直接创建对象
Student stu = (Student) con.newInstance("zhangsan", 23);
System.out.println(stu);
1.7 获取成员变量
规则:
get表示获取
Declared表示私有
最后的s表示所有,复数形式
如果当前获取到的是私有的,必须要临时修改访问权限,否则无法使用
方法名:
| 方法名 | 说明 |
|---|---|
| Field[] getFields() | 返回所有成员变量对象的数组(只能拿public的) |
| Field[] getDeclaredFields() | 返回所有成员变量对象的数组,存在就能拿到 |
| Field getField(String name) | 返回单个成员变量对象(只能拿public的) |
| Field getDeclaredField(String name) | 返回单个成员变量对象,存在就能拿到 |
代码示例:
public class ReflectDemo4 {public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {//获取成员变量对象//1.获取class对象Class clazz = Class.forName("com.itheima.reflectdemo.Student");//2.获取成员变量的对象(Field对象)只能获取public修饰的Field[] fields1 = clazz.getFields();for (Field field : fields1) {System.out.println(field);}System.out.println("===============================");//获取成员变量的对象(public + private)Field[] fields2 = clazz.getDeclaredFields();for (Field field : fields2) {System.out.println(field);}System.out.println("===============================");//获得单个成员变量对象//如果获取的属性是不存在的,那么会报异常//Field field3 = clazz.getField("aaa");//System.out.println(field3);//NoSuchFieldExceptionField field4 = clazz.getField("gender");System.out.println(field4);System.out.println("===============================");//获取单个成员变量(私有)Field field5 = clazz.getDeclaredField("name");System.out.println(field5);}
}public class Student {private String name;private int age;public String gender;public String address;public Student() {}public Student(String name, int age, String address) {this.name = name;this.age = age;this.address = address;}public Student(String name, int age, String gender, String address) {this.name = name;this.age = age;this.gender = gender;this.address = address;}//get,set方法public String toString() {return "Student{name = " + name + ", age = " + age + ", gender = " + gender + ", address = " + address + "}";}
}
1.8 获取成员变量并获取值和修改值
| 方法 | 说明 |
|---|---|
| void set(Object obj, Object value) | 赋值 |
| Object get(Object obj) | 获取值 |
代码示例:
public class ReflectDemo5 {public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {Student s = new Student("zhangsan",23,"广州");Student ss = new Student("lisi",24,"北京");//需求://利用反射获取成员变量并获取值和修改值//1.获取class对象Class clazz = Class.forName("com.itheima.reflectdemo.Student");//2.获取name成员变量//field就表示name这个属性的对象Field field = clazz.getDeclaredField("name");//临时修饰他的访问权限field.setAccessible(true);//3.设置(修改)name的值//参数一:表示要修改哪个对象的name?//参数二:表示要修改为多少?field.set(s,"wangwu");//3.获取name的值//表示我要获取这个对象的name的值String result = (String)field.get(s);//4.打印结果System.out.println(result);System.out.println(s);System.out.println(ss);}
}public class Student {private String name;private int age;public String gender;public String address;public Student() {}public Student(String name, int age, String address) {this.name = name;this.age = age;this.address = address;}public Student(String name, int age, String gender, String address) {this.name = name;this.age = age;this.gender = gender;this.address = address;}
//get,set 方法public String toString() {return "Student{name = " + name + ", age = " + age + ", gender = " + gender + ", address = " + address + "}";}
}
1.9 获取成员方法
规则:
get表示获取
Declared表示私有
最后的s表示所有,复数形式
如果当前获取到的是私有的,必须要临时修改访问权限,否则无法使用
| 方法名 | 说明 |
|---|---|
| Method[] getMethods() | 返回所有成员方法对象的数组(只能拿public的) |
| Method[] getDeclaredMethods() | 返回所有成员方法对象的数组,存在就能拿到 |
| Method getMethod(String name, Class<?>… parameterTypes) | 返回单个成员方法对象(只能拿public的) |
| Method getDeclaredMethod(String name, Class<?>… parameterTypes) | 返回单个成员方法对象,存在就能拿到 |
代码示例:
public class ReflectDemo6 {public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {//1.获取class对象Class<?> clazz = Class.forName("com.itheima.reflectdemo.Student");//2.获取方法//getMethods可以获取父类中public修饰的方法Method[] methods1 = clazz.getMethods();for (Method method : methods1) {System.out.println(method);}System.out.println("===========================");//获取所有的方法(包含私有)//但是只能获取自己类中的方法Method[] methods2 = clazz.getDeclaredMethods();for (Method method : methods2) {System.out.println(method);}System.out.println("===========================");//获取指定的方法(空参)Method method3 = clazz.getMethod("sleep");System.out.println(method3);Method method4 = clazz.getMethod("eat",String.class);System.out.println(method4);//获取指定的私有方法Method method5 = clazz.getDeclaredMethod("playGame");System.out.println(method5);}
}
1.10 获取成员方法并运行
方法
Object invoke(Object obj, Object… args) :运行方法
参数一:用obj对象调用该方法
参数二:调用方法的传递的参数(如果没有就不写)
返回值:方法的返回值(如果没有就不写)
代码示例:
package com.itheima.a02reflectdemo1;import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;public class ReflectDemo6 {public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {//1.获取字节码文件对象Class clazz = Class.forName("com.itheima.a02reflectdemo1.Student");//2.获取一个对象//需要用这个对象去调用方法Student s = new Student();//3.获取一个指定的方法//参数一:方法名//参数二:参数列表,如果没有可以不写Method eatMethod = clazz.getMethod("eat",String.class);//运行//参数一:表示方法的调用对象//参数二:方法在运行时需要的实际参数//注意点:如果方法有返回值,那么需要接收invoke的结果//如果方法没有返回值,则不需要接收String result = (String) eatMethod.invoke(s, "重庆小面");System.out.println(result);}
}public class Student {private String name;private int age;public String gender;public String address;public Student() {}public Student(String name) {this.name = name;}private Student(String name, int age) {this.name = name;this.age = age;}//get,set 方法public String toString() {return "Student{name = " + name + ", age = " + age + "}";}private void study(){System.out.println("学生在学习");}private void sleep(){System.out.println("学生在睡觉");}public String eat(String something){System.out.println("学生在吃" + something);return "学生已经吃完了,非常happy";}
}
面试题:
你觉得反射好不好?好,有两个方向
第一个方向:无视修饰符访问类中的内容。但是这种操作在开发中一般不用,都是框架底层来用的。
第二个方向:反射可以跟配置文件结合起来使用,动态的创建对象,动态的调用方法。
后记
👉👉💕💕美好的一天,到此结束,下次继续努力!欲知后续,请看下回分解,写作不易,感谢大家的支持!! 🌹🌹🌹
相关文章:
从零开始学习 Java:简单易懂的入门指南之反射(三十八)
反射 1. 反射1.1 反射的概述:1.2 学习反射到底学什么?1.3 获取字节码文件对象的三种方式1.4 字节码文件和字节码文件对象1.5 获取构造方法1.6 获取构造方法并创建对象1.7 获取成员变量1.8 获取成员变量并获取值和修改值1.9 获取成员方法1.10 获取成员方法…...
【七:(测试用例)spring boot+testng+xml+mock实现用例管理+数据校验】
目录 1、目录结构的相关类cases类1、添加用户 AddUserTest2、获取用户列表信息 GetUserInfoListTest3、获取用户信息 GetUserInfoTest4、登录测试5、更新用户信息 config类1、报告配置2、用户路径配置 model类utils类 配置配置类SQLMapper.xmlspring boot全局配置databaseConfi…...
哪些数据应该先治理
在我们提供的数据中,哪些是真正需要优先治理的呢?这是任何数据治理项目开始之前都需要解决的问题。正确地确定了数据治理的优先级,不仅可以帮助我们将有限的资源用在刀刃上,更能实现数据治理的最大价值。下面数聚就深度为企业管理…...
No module ‘xformers‘. Proceeding without it.
一、背景: 运行提示 No module xformers. Proceeding without it. 二、分析 1、xformers是SD的加速模块,没有他可以继续运行,可以正常生成图片。只是xformers可以帮助提升图片的生成速度。 2、安装完SD后,启动出现xformers未安…...
Stable Diffusion WebUI报错RuntimeError: Torch is not able to use GPU解决办法
新手在安装玩Stable Diffusion WebUI之后会遇到各种问题, 接下来会慢慢和你讲解如何解决这些问题。 在我们打开Stable Diffusion WebUI时会报错如下: RuntimeError: Torch is not able to use GPU;add --skip-torch-cuda-test to COMMANDL…...
金融信息化研究所与YashanDB等单位启动金融多主数据库应用行动计划
10月13日,2023金融业 数据库技术大会在京成功召开。会上,金融信息化研究所与崖山数据库YashanDB、阿里巴巴、奥星贝斯、达梦、南大通用、华为、天翼云、万里数据库、优炫数据库共同启动金融多主数据库应用行动计划,并成立金融多主数据库应用…...
工具篇之Axure RP 10的使用
引言 最近在学习原型图,针对画原型图的工具,反复对比墨刀、Axure、xiaopiu后,最终选择Axure。 接下来,我便从Axure RP 10的下载、安装、中文字体、授权等几个方面,来介绍Axure。 一、背景 Axure是一款强大的原型设计…...
C#选择排序(Selection Sort)算法
选择排序(Selection Sort)原理介绍 选择排序(Selection Sort)是一种简单的排序算法,其实现原理如下: 遍历待排序数组,从第一个元素开始。 假设当前遍历的元素为最小值,将其索引保存…...
【Mysql】InnoDB数据页结构(五)
概述 页是InnoDB存储引擎管理存储空间的基本单位,一个页的大小默认是16KB 。InnoDB 为了不同的目的而设计了许多种不同类型的页 ,比如存放记录的索引页,存放表空间头部信息的页,存放 Insert Buffer信息的页,存放 INOD…...
Golang中的type关键字
type关键字在Go语言中有五种用法: 定义结构体定义接口类型别名类型定义类型开关其中,定义结构体和定义接口是Go语言中常用的类型定义方式,类型别名和类型定义则是为了方便程序员使用而设计的,而类型开关则是Go语言中比较特殊的一种类型定义方式。 定义结构体 结构体是由一…...
网站管家机器人在为企业获客方面起什么作用?
随着科技的不断进步和人们对便捷服务的需求增加,网站管家机器人成为了现代企业获客的重要工具。作为一种基于人工智能技术的在线助手,网站管家机器人可以与访问企业网站的用户进行智能对话,并提供即时的帮助和解答。 网站管家机器人在为企业获…...
竞赛选题 深度学习交通车辆流量分析 - 目标检测与跟踪 - python opencv
文章目录 0 前言1 课题背景2 实现效果3 DeepSORT车辆跟踪3.1 Deep SORT多目标跟踪算法3.2 算法流程 4 YOLOV5算法4.1 网络架构图4.2 输入端4.3 基准网络4.4 Neck网络4.5 Head输出层 5 最后 0 前言 🔥 优质竞赛项目系列,今天要分享的是 🚩 *…...
零基础学习HTML5
1. 使用软件 vscode 谷歌浏览器 vscode下载地址:https://code.visualstudio.com/ 谷歌可以使用360软件管家安装 2. 安装插件 在vscode中安装插件:open in browser,点击Extensions后搜索对应插件名然后点击安装Install 安装完成后可在htm…...
Jenkins 部署 Maven项目很慢怎么办?
Jenkins 部署 Maven项目很慢怎么办? 答案是:使用阿里云的Maven仓库 <mirror><id>aliyunmaven</id><mirrorOf>*</mirrorOf><name>阿里云公共仓库</name><url>https://maven.aliyun.com/repository/pub…...
关于刷题时使用数组的小注意事项
💯 博客内容:关于刷题时使用数组的小技巧 😀 作 者:陈大大陈 🚀 个人简介:一个正在努力学技术的准前端,专注基础和实战分享 ,欢迎私信! 💖 欢迎大家&#…...
【MySQL】面试题
引言 :MySQL面试题及答案 【最新版】 目录 1、NOW()和CURRENT_DATE()有什么区别?2、CHAR和VARCHAR的区别?3、主键索引与唯一索引的区别4、MySQL中有哪些不同的表格?5、SQL的生命周期…...
Pytorch训练深度强化学习时CPU内存占用一直在快速增加
最近在用MATD3算法解决多机器人任务,但是在训练过程中,CPU内存一直在增加(注意,不是GPU显存)。我很头疼,以为是算法代码出了问题,导致了内存泄漏,折腾了1天也没解决。后来用memory_p…...
git第一次推送出现推送被拒绝
前言 git 第一次推送出现以下错误 ! [rejected] master -> master (fetch first) error: failed to push some refs to ‘https://gitee.com/fengshangyunwang/iot-front-end.git’ hint: Updates were rejected because the remote contains work that you do hint: not …...
CRC16计算FC(博途SCL语言)
CRC8的计算FC,相关链接请查看下面文章链接: 博途SCL CRC8 计算FC(计算法)_博途怎么计算crc_RXXW_Dor的博客-CSDN博客关于CRC8的计算网上有很多资料和C代码,这里不在叙述,这里主要记录西门子的博途SCL完成CRC8的计算过程, CRC校验算法,说白了,就是把需要校验的数据与多项式…...
setsockopt()函数的用法
setsockopt() 函数是一个用于设置套接字选项的函数,通常在网络编程中使用。它用于配置套接字的各种参数和选项,以满足特定的需求。setsockopt() 函数的作用是设置指定套接字选项的值。 setsockopt() 函数的一般用法: int setsockopt(int soc…...
UDP(Echoserver)
网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法:netstat [选项] 功能:查看网络状态 常用选项: n 拒绝显示别名&#…...
汽车生产虚拟实训中的技能提升与生产优化
在制造业蓬勃发展的大背景下,虚拟教学实训宛如一颗璀璨的新星,正发挥着不可或缺且日益凸显的关键作用,源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例,汽车生产线上各类…...
2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面
代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口(适配服务端返回 Token) export const login async (code, avatar) > {const res await http…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...
node.js的初步学习
那什么是node.js呢? 和JavaScript又是什么关系呢? node.js 提供了 JavaScript的运行环境。当JavaScript作为后端开发语言来说, 需要在node.js的环境上进行当JavaScript作为前端开发语言来说,需要在浏览器的环境上进行 Node.js 可…...
js 设置3秒后执行
如何在JavaScript中延迟3秒执行操作 在JavaScript中,要设置一个操作在指定延迟后(例如3秒)执行,可以使用 setTimeout 函数。setTimeout 是JavaScript的核心计时器方法,它接受两个参数: 要执行的函数&…...
Copilot for Xcode (iOS的 AI辅助编程)
Copilot for Xcode 简介Copilot下载与安装 体验环境要求下载最新的安装包安装登录系统权限设置 AI辅助编程生成注释代码补全简单需求代码生成辅助编程行间代码生成注释联想 代码生成 总结 简介 尝试使用了Copilot,它能根据上下文补全代码,快速生成常用…...
深入理解 C++ 左值右值、std::move 与函数重载中的参数传递
在 C 编程中,左值和右值的概念以及std::move的使用,常常让开发者感到困惑。特别是在函数重载场景下,如何合理利用这些特性来优化代码性能、确保语义正确,更是一个值得深入探讨的话题。 在开始之前,先提出几个问题&…...
智能体革命:企业如何构建自主决策的AI代理?
OpenAI智能代理构建实用指南详解 随着大型语言模型(LLM)在推理、多模态理解和工具调用能力上的进步,智能代理(Agents)成为自动化领域的新突破。与传统软件仅帮助用户自动化流程不同,智能代理能够自主执行工…...
uni-app学习笔记二十七--设置底部菜单TabBar的样式
官方文档地址:uni.setTabBarItem(OBJECT) | uni-app官网 uni.setTabBarItem(OBJECT) 动态设置 tabBar 某一项的内容,通常写在项目的App.vue的onLaunch方法中,用于项目启动时立即执行 重要参数: indexnumber是tabBar 的哪一项&…...
