从零开始学习 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…...

【AOP系列】6.缓存处理
在Java中,我们可以使用Spring AOP(面向切面编程)和自定义注解来做缓存处理。以下是一个简单的示例: 首先,我们创建一个自定义注解,用于标记需要进行缓存处理的方法: import java.lang.annotat…...

云函数cron-parser解析时区问题
1、问题 云函数部署后cron-parser解析0点会变成8点 考虑可能是时区的问题 然后看文档发现果然有问题,云函数环境是utc0 2、解决 看了半天cron-parser文档发现 Using Date as an input can be problematic specially when using the tz option. The issue bein…...

Android11修改自动允许连接到建议的WLAN网络
客户的app需要连接指定的wifi,但是会提示下面的对话框(是否允许系统连接到建议的WLAN网络?): 客户需求:不提示这个对话框自动允许。 根据字符串定位到frameworks\opt\net\wifi\service\java\com\android\server\wifi\WifiNetworkSuggestionsManager.java 中的privat…...

基于Qt HTTP应用程序项目案例
文章目录 主项目入口项目子头文件httpwindow.hhttpwindow.h源文件httpwindow.cppui文件效果演示主项目入口 main函数创建对象空间,确认窗口的大小和坐标。 #include <QApplication> #include <QDir> #include...

OpenGL —— 2.7、绘制多个自旋转的贴图正方体(附源码,glfw+glad)
源码效果 C源码 纹理图片 需下载stb_image.h这个解码图片的库,该库只有一个头文件。 具体代码: vertexShader.glsl #version 330 corelayout(location 0) in vec3 aPos; layout(location 1) in vec2 aUV;out vec2 outUV;uniform mat4 _modelMatrix; …...

linux之perf(8)annotate标注
Linux之perf(8)annotate标注 Author:Onceday Date:2023年10月12日 漫漫长路,才刚刚开始… 注:该文档内容采用了GPT4.0生成的回答,部分文本准确率可能存在问题。 参考文档: Tutorial - Perf Wiki (kernel.org)perf…...

【广州华锐互动】VR建筑安全培训体验为建筑行业人才培养提供有力支持
随着建筑行业的快速发展,建筑施工安全问题日益受到广泛关注。然而,传统的安全培训方式往往缺乏实践性和真实性,难以让员工真正掌握安全操作技能。近年来,虚拟现实(VR)技术的广泛应用为建筑施工安全培训提供了新的机遇。 虚拟现实技…...

【Javascript保姆级教程】运算符
文章目录 前言一、运算符是什么二、赋值运算符2.1 如何使用赋值运算符2.2 示例代码12.3 示例代码2 三、自增运算符3.1 运算符3.2 示例代码13.3 示例代码2 四、比较运算符4.1 常见的运算符4.2 如何使用4.3 示例代码14.4 示例代码2 五、逻辑运算符逻辑运算符列举 六、运算符优先级…...

图论与网络优化
2.概念与计算 2.1 图的定义 2.1.1 定义 图(graph) G G G 是一个有序的三元组,记作 G < V ( G ) , E ( G ) , ψ ( G ) > G<V(G),E(G),\psi (G)> G<V(G),E(G),ψ(G)>。 V ( G ) V(G) V(G) 是顶点集。 E ( G ) E(G) E(G) 是边集。 ψ ( G ) \…...

【论文复现】基于多模态深度学习方法的单细胞多组学数据聚类(【生物信息学】实验二:多组学数据融合:scMDC)
目录 一、实验介绍 1. 论文:基于多模态深度学习方法的单细胞多组学数据聚类 Abstract 2. Github链接 二、实验环境 0. 作者要求 1. 环境复现 实验一 实验二(本实验) 2. 库版本介绍 实验一 实验二 3. IDE 三、实验内容 1. 用法…...