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

【Java学习】反射和枚举详解

  所属专栏:Java学习 

在这里插入图片描述

🍁1. 反射

在程序运行时,可以动态地创建对象、调用方法、访问和修改字段,以及获取类的各种属性信息(如成员变量、方法、构造函数等),这种机制就称为反射

反射相关的类
类名用途
Class类代表类的实体,在运行的Java应用程序中表示类和接口
Field类代表类的成员变量 / 类的属性
Method类代表类的方法
Constructor类代表类的构造方法

🍁1.1 反射获取Class对象 

获取字节码文件对象

1. Class.forName(全类名) 包名 + 类名

2. 类名.class

3. 对象名.getClass()

public class Demo1 {public static void main(String[] args) throws ClassNotFoundException {//获取字节码文件对象的三种方式// Class.forName(全类名)包名 + 类名(常用)Class clazz1 = Class.forName("reflect.Student");//类名.classClass clazz2 = Student.class;//对象名.getClass()Student student = new Student();Class clazz3 = student.getClass();System.out.println(clazz1 == clazz2);System.out.println(clazz2 == clazz3);}
}

🍁1.2 反射获取构造方法

🍁1.2.1 获取构造方法的方式

方法用途
getConstructor(Class...<?> parameterTypes)获得该类中与参数类型匹配的公有构造方法
getConstructors()获得该类的所有公有构造方法对象的数组
getDeclaredConstructor(Class...<?> parameterTypes)获得该类中与参数类型匹配的构造方法
getDeclaredConstructors()获得该类所有构造方法对象的数组

使用 getConstructors()时,只会获取类中的公共的构造方法

可以看出,使用getDeclaredConstructors()时,不论构造方法的权限修饰符是什么,都可以获取到 

来看获取单个构造方法的例子,在调用方法的时候,传入方法里面的参数要和需要获取的构造方法的参数一致 

 getConstructor 只能获取 public 修饰的构造方法,getDeclaredConstructor可以获取任意修饰符修饰的构造方法,所以如果要获取的构造方法如果不是 public 修饰的,但是使用了getConstructor获取,就会报错

public class Demo2 {public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {//获取class字节码文件对象Class clazz = Class.forName("com.li.reflect.Student");//获取构造方法Constructor[]  cons1 = clazz.getConstructors();for (Constructor con : cons1) {System.out.println(con);}Constructor[] cons2 = clazz.getDeclaredConstructors();for (Constructor con2 : cons2) {System.out.println(con2);}//获取单个的构造方法Constructor con1 = clazz.getDeclaredConstructor();System.out.println(con1);Constructor con2 = clazz.getDeclaredConstructor(String.class);System.out.println(con2);Constructor con3 = clazz.getDeclaredConstructor(String.class,int.class);System.out.println(con3);Constructor con4 = clazz.getDeclaredConstructor(int.class);System.out.println(con2);}
}

 student类:

public class Student {private String name;private int age;public Student() {}private Student(int age){this.age = age;}protected Student(String name){this.name = name;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}public Student(String name, int age) {this.name = name;this.age = age;}
}

🍁1.2.2 获取构造方法的用途

通过反射,可以获取到构造方法的所有内容

首先第一个,就是可以获取到构造方法的权限修饰符

//获取权限修饰符,这里获取的是其对应的常量值
int modifiers = con1.getModifiers();
System.out.println(modifiers); //public 对应的常量是1

idea中的提示功能就是使用了反射的机制,获取到了构造方法的权限修饰符,这里只提示了除空参构造之外,可以使用的两种构造方法,private由于在其他类中不能调用,这里就没有显示

之后,还可以获取到构造方法的参数 

//获取参数
Parameter[] parameters = con3.getParameters();
System.out.println(Arrays.toString(parameters));//[java.lang.String arg0, int arg1]

 应用场景还是上面的代码提示功能

既然可以获取构造方法的所有内容,那以此来创建一个对象也是可以的:

        //创建对象Student student1 = (Student) con3.newInstance("张三", 18);System.out.println(student1);//获取到private修饰的构造方法时con4.setAccessible(true); //表示临时取消权限校验Student student2 = (Student) con4.newInstance(18);System.out.println(student2);

用这种方式创建对象需要注意:

传进去的参数要和获取到的构造方法的参数一致

如果获取到 private修饰的构造方法时,需要临时取消权限校验

🍁1.3 反射获取成员变量

🍁1.3.1 获取成员变量的方式

方法用途
getField(String name)获得某个公有的属性对象
getFields()获得所有公有的属性对象的数组
getDeclaredField(String name)获得某个属性对象
getDeclaredFields()获得所有属性对象的数组

  

public class Demo3 {public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {//获取字节码文件的对象Class clazz = Class.forName("com.li.reflect.Student");//获取所有的成员变量Field[] fields1 = clazz.getFields();System.out.println(Arrays.toString(fields1));Field[] fields = clazz.getDeclaredFields();for (Field field : fields) {System.out.println(field);}//获取单个成员变量Field res1 = clazz.getField("gender");System.out.println(res1);Field res2 = clazz.getDeclaredField("name");System.out.println(res2);}
}

这里的方法的区别对比着获取构造方法的区别是一样的 

在获取单个的成员变量时,传入的参数是要获取的变量名 

🍁1.3.2 获取成员变量的用途

可以获取到成员变量的权限修饰符,名称,数据类型

        //获取成员变量的权限修饰符int modifiers = res1.getModifiers();System.out.println(modifiers);//获取成员变量的名称String name = res1.getName();System.out.println(name);//获取成员变量的数据类型Class<?> type = res1.getType();System.out.println(type);

此外,还可以获取到当前成员变量记录的值

        //获取成员变量记录的值Student student = new Student("张三",18,"男");//临时取消权限校验res1.setAccessible(true);Object value = res1.get(student);System.out.println(value);

 这里需要注意的是,如果获取的值是private修饰的,还是需要设置临时取消权限校验

 获取到值之后,还可以进行修改

//修改
res1.set(student,"女");
System.out.println(student);

🍁1.4 反射获取成员方法

🍁1.4.1 获取成员方法的方式

方法用途
getMethod(String name, Class...<?> parameterTypes)获得该类某个公有的方法
getMethods()获得该类所有公有的方法的数组,包括继承的
getDeclaredMethod(String name, Class...<?> parameterTypes)获得该类某个方法
getDeclaredMethods()获得该类所有方法的数组,不包括继承的

getMethods()  获取的是该类所有公有的方法的数组,包括继承的,所以显示出了很多Person类本身没有定义的方法

 getDeclaredMethods()获取的是该类所有方法的数组,不包括继承的,

获取指定的方法:

在使用getDeclaredMethod获取指定方法时,第一个参数需要指定方法的名称,第二个参数需要指定方法的形参,如果是空参,那么第二个参数就空着不写

        //获取指定方法Method m = clazz.getDeclaredMethod("eat",String.class);System.out.println(m);

🍁1.4.2 获取成员方法的用途

可以获取方法的修饰符,名字,方法的形参,以及方法抛出的异常

        //获取方法修饰符int modifiers = m.getModifiers();System.out.println(modifiers);//获取方法的名字String name = m.getName();System.out.println(name);//获取方法的形参Parameter[] parameters = m.getParameters();for (Parameter parameter : parameters) {System.out.println(parameter);}//获取方法抛出的异常Class[] exceptionTypes = m.getExceptionTypes();for (Class exceptionType : exceptionTypes) {System.out.println(exceptionType);}

获取到的方法也可以通过调用 invoke 方法运行

    /*Object invoke(Object obj,Object...args):运行方法参数一:用obj对象调用该方法参数二:调用方法的传递的参数(如果没有就不写)返回值:方法的返回值(如果没有就不写)* */Person person = new Person();m.setAccessible(true);//如果有返回值可以接收Object res = m.invoke(person, "饭");//打印返回值System.out.println(res);

🍁2. 枚举

 枚举是一种特殊的类,枚举中的每个元素都是该类的一个唯一实例,主要用途是把一组常量组织起来

在之前我们定义常量的时候是这样定义的:

public static final int RED = 1;

但是如果恰好此时有一个数字1,就可能被误认为是RED,这时就可以通过枚举来组织常量 

在创建类时选择Enum类进行创建

🍁2.1 枚举的使用 

Enum类中的常用方法 

方法名称描述
values()以数组形式返回枚举类型的所有成员
ordinal()获取枚举成员的索引位置
valueOf()将普通字符串转换为枚举实例
compareTo()比较两个枚举成员在定义时的顺序
public enum EnumDemo1 {RED, BLACK, YELLO, BLUE;public static void main(String[] args) {EnumDemo1[] enumDemo1s = EnumDemo1.values();for (int i = 0; i < enumDemo1s.length; i++) {System.out.println(enumDemo1s[i] + " " + enumDemo1s[i].ordinal());}//根据字符串返回类中的实例EnumDemo1 res = EnumDemo1.valueOf("RED");System.out.println(res);//比较定义顺序System.out.println(RED.compareTo(BLUE));}
}

可以和switch语句一起使用:

public enum EnumDemo1 {RED, BLACK, YELLO, BLUE;public static void main(String[] args) {EnumDemo1 e1 = RED;switch (e1) {case RED:System.out.println("RED");break;case BLACK:System.out.println("BLACK");default:System.out.println("无法匹配");}}
}

🍁2.2 枚举类的构造方法

在之前提到过,枚举本身是一个类,如果想要类里面的实例对象有参数的话,需要提供相应的构造方法,并且构造方法默认是私有的

public enum EnumDemo2 {RED(0, "red"), BLACK(1, "black"),YELLO(2, "yello"), BLUE(3, "blue");private int ordinal;private String color;EnumDemo2() {}private EnumDemo2(int ordinal, String color) {this.ordinal = ordinal;this.color = color;}
}

 如果将构造方法设置为除private外的其他类型的话就会报错

🍁2.3 枚举在反射中的特殊情况

还按照之前反射的方法获取构造方法并创建对象时,会发现报错了,并且给出的异常是没有找到这个构造方法,但是我们的EnumDemo2类中是存在这个方法的

自己定义的枚举类是默认继承Enum类的,会优先代用父类的构造方法,所以就需要加上父类的参数,此时就解决了第一个异常

此时通过查看newInstance的源码发现,只要是枚举类,就会报错,所以说枚举类是比较安全的

在这里插入图片描述


 

相关文章:

【Java学习】反射和枚举详解

所属专栏&#xff1a;Java学习 &#x1f341;1. 反射 在程序运行时&#xff0c;可以动态地创建对象、调用方法、访问和修改字段&#xff0c;以及获取类的各种属性信息&#xff08;如成员变量、方法、构造函数等&#xff09;&#xff0c;这种机制就称为反射 反射相关的类 类名用…...

leetcode-461. 汉明距离

题目描述 两个整数之间的 汉明距离 指的是这两个数字对应二进制位不同的位置的数目。 给你两个整数 x 和 y&#xff0c;计算并返回它们之间的汉明距离。 示例 1&#xff1a; 输入&#xff1a;x 1, y 4 输出&#xff1a;2 解释&#xff1a; 1 (0 0 0 1) 4 (0 1 0 0) …...

rpmbuild 将二进制文件 strip,文件 md5 发生改变

rpmbuild 将二进制文件 strip&#xff0c;文件 md5 发生改变 上一篇中提到 strip 相关的操作&#xff0c;会去掉文件中的调试信息【strip 、objdump、objcopy 差异与区别】 在编译或打包环境中&#xff0c;莫名其妙的文件 大小 md5 都发生了改变&#xff0c;怀疑跟 rpmbuild 打…...

selenium爬取搜狗网站新闻的小Demo

使用之前请确保自己chrome浏览的版本与chromedriver的版本一致&#xff0c; Mac确保chromedriver已经放到python的bin目录中 Windows确保chromedriver已经放到python.exe同目录中 当前selenium Version: 3.141.0&#xff0c;4版本后面改为&#xff1a;find_element(By.CLASS_NA…...

R 语言学习教程,从入门到精通,R CSV 文件使用(17)

1、R CSV 文件 R 作为统计学专业工具&#xff0c;如果只能人工的导入和导出数据将使其功能变得没有意义&#xff0c;所以 R 支持批量的从主流的表格存储格式文件&#xff08;例如 CSV、Excel、XML 等&#xff09;中获取数据。 1.1、CSV 表格交互 CSV&#xff08;Comma-Separ…...

【LLM之Base Model】Weaver论文阅读笔记

研究背景 当前的大型语言模型&#xff08;LLM&#xff09;如GPT-4等&#xff0c;尽管在普通文本生成中表现出色&#xff0c;但在创造性写作如小说、社交媒体内容等方面&#xff0c;往往不能很好地模仿人类的写作风格。这些模型在训练和对齐阶段&#xff0c;往往使用的是大规模…...

泰坦尼克号 - 从灾难中学习机器学习/Titanic - Machine Learning from Disaster(kaggle竞赛)第一集(了解赛题)

此次目的&#xff1a; hello大家好&#xff0c;俺是没事爱瞎捣鼓又分享欲爆棚的叶同学&#xff01;&#xff01;&#xff01;准备出几期博客来记录我学习kaggle数据科学入门竞赛的过程&#xff0c;顺便也将其中所学习到的知识分享出来。这是第一集&#xff08;了解赛题&#x…...

使用C++调用PyTorch模型的弯弯绕绕,推荐LibTorch加载,C++处理

需求&#xff1a;使用C调用Pytorch模型&#xff0c;对处理后的图像进行预测。 第一种&#xff0c;使用C调用Python代码处理&#xff0c;使用pybind11源代码再末尾 缺点&#xff0c;导入Python包非常麻烦&#xff0c;执行的C程序找不到cv2 torch包等等 本人解决了cv2 numpy等包&…...

实现异形(拱形)轮播图

项目需要实现如上图所示的轮播图。 实现思路&#xff1a; 1.项目引入使用普通轮播图。 2.根据轮播图个数&#xff0c;动态给可视范围的第一个轮播图和最后一个轮播图添加样式。 代码实现&#xff1a; 经调研&#xff0c;使用slick轮播图&#xff08;官网地址 https://kenwheel…...

【软件测试】2024年职业院校技能大赛高职组“软件测试”赛项样题

目录 任务一&#xff1a;功能测试&#xff08;45 分&#xff09; 任务二&#xff1a;自动化测试&#xff08;15 分&#xff09; 任务三&#xff1a;性能测试&#xff08;15 分&#xff09; 任务四&#xff1a;单元测试&#xff08;10 分&#xff09; 任务五&#xff1a;接…...

python数组和队列

一、数组 如果一个列表只包含数值&#xff0c;那么使用array.array会更加高效&#xff0c;数组不仅支持所有可变序列操作&#xff08;.pop、.insert、.extent等&#xff09;&#xff0c;而且还支持快速加载项和保存项的方法&#xff08;.fromfile、.tofile等&#xff09; 创建…...

Vision Transformer(ViT)一种将Transformer架构应用于计算机视觉领域的模型

Vision Transformer&#xff08;ViT&#xff09;是一种将Transformer架构应用于计算机视觉领域的模型&#xff0c;它通过自注意力机制处理图像数据&#xff0c;与传统的卷积神经网络&#xff08;CNN&#xff09;相比&#xff0c;ViT能够更好地捕捉全局依赖关系。以下是对ViT的详…...

得到任务式 大模型应用开发学习方案

根据您提供的文档内容以及您制定的大模型应用开发学习方案&#xff0c;我们可以进一步细化任务式学习的计划方案。以下是具体的任务式学习方案&#xff1a; 任务设计 初级任务 大模型概述&#xff1a;阅读相关资料&#xff0c;总结大模型的概念、发展历程和应用领域。深度学…...

使用el-menu跳转时偶尔会出现路由已经变了,但是页面却显示空白的情况

刚开始我以为是我数据加载的问题&#xff0c;后来又看有人说是template里不能包多个div&#xff0c;但我去看我出错的组件&#xff0c;并没有出现两个div。 后来我就把每个都给改了&#xff0c;即使是elemen-ui的标签也全部改在一个div里&#xff0c;就发现没问题了。 我改的…...

C语言家教记录(七)

C语言家教记录&#xff08;七&#xff09; 导语字符串字面量变量读写字符串操作函数惯用法数组 结构联合枚举总结与复习 导语 本次授课的内容如下&#xff1a;字符串&#xff0c;结构体、联合体、枚举 辅助教材为 《C语言程序设计现代方法&#xff08;第2版&#xff09;》 字…...

【数据结构】——十大排序详解分析及对比

【数据结构】——十大排序详解分析及对比 文章目录 【数据结构】——十大排序详解分析及对比前言1. 排序的概念及其运用1.1 排序的概念1.2 排序的应用 2. 插入排序2.1 直接插入排序2.2 希尔排序 3. 选择排序3.1 选择排序3.2 堆排序 4 交换排序4.1 冒泡排序4.2 快速排序4.2.1 霍…...

散点图适用于什么数据 thinkcell散点图设置不同颜色

在数据可视化的众多工具和技巧中&#xff0c;散点图是一种极为有效的方式&#xff0c;能够揭示变量之间的关系&#xff0c;尤其是在探索数据集的相关性、分布趋势、集群现象时。而在众多助力于制作高质量散点图的工具中&#xff0c;think-cell插件以其高效的操作和丰富的功能&a…...

1. windows搭建Kafka教程

目录 1. 部署zookeeper 1.1 下载地址 1.3 修改zoo配置 1.4 启动zookeepe服务 02 部署kafka 2.1 下载组件包 2.2 解压安装包 2.3 修改配置 2.4 启动kafka服务端 1. 部署zookeeper 1.1 下载地址 下载地址: kafka/zookeeper 下载地址 (qq.com) 1.2 解压 &#xff08;…...

XSS复现

目录 XSS简单介绍 一、反射型 1、漏洞逻辑&#xff1a; 为什么有些标签可以触发&#xff0c;有些标签不能触发 可以触发的标签 不能触发的标签 为什么某些标签能触发而某些不能 二、DOM型 1、Ma Spaghet! 要求&#xff1a; 分析&#xff1a; 结果&#xff1a; 2、J…...

怎么利用XML发送视频彩信

传统的短信推广主要以文字为主&#xff0c;用户接收到的信息往往显得单调乏味。而视频彩信则不同&#xff0c;它结合了视频和音频的优势&#xff0c;通过生动的画面和悦耳的音乐&#xff0c;给用户带来强烈的视听冲击&#xff0c;从而极大地提高了用户的吸引力。 XML成功返回示…...

python打卡day49

知识点回顾&#xff1a; 通道注意力模块复习空间注意力模块CBAM的定义 作业&#xff1a;尝试对今天的模型检查参数数目&#xff0c;并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...

3403. 从盒子中找出字典序最大的字符串 I

3403. 从盒子中找出字典序最大的字符串 I 题目链接&#xff1a;3403. 从盒子中找出字典序最大的字符串 I 代码如下&#xff1a; class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...

select、poll、epoll 与 Reactor 模式

在高并发网络编程领域&#xff0c;高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表&#xff0c;以及基于它们实现的 Reactor 模式&#xff0c;为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。​ 一、I…...

优选算法第十二讲:队列 + 宽搜 优先级队列

优选算法第十二讲&#xff1a;队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...

使用 SymPy 进行向量和矩阵的高级操作

在科学计算和工程领域&#xff0c;向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能&#xff0c;能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作&#xff0c;并通过具体…...

Angular微前端架构:Module Federation + ngx-build-plus (Webpack)

以下是一个完整的 Angular 微前端示例&#xff0c;其中使用的是 Module Federation 和 npx-build-plus 实现了主应用&#xff08;Shell&#xff09;与子应用&#xff08;Remote&#xff09;的集成。 &#x1f6e0;️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...

【Redis】笔记|第8节|大厂高并发缓存架构实战与优化

缓存架构 代码结构 代码详情 功能点&#xff1a; 多级缓存&#xff0c;先查本地缓存&#xff0c;再查Redis&#xff0c;最后才查数据库热点数据重建逻辑使用分布式锁&#xff0c;二次查询更新缓存采用读写锁提升性能采用Redis的发布订阅机制通知所有实例更新本地缓存适用读多…...

云原生安全实战:API网关Kong的鉴权与限流详解

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关&#xff08;API Gateway&#xff09; API网关是微服务架构中的核心组件&#xff0c;负责统一管理所有API的流量入口。它像一座…...

iview框架主题色的应用

1.下载 less要使用3.0.0以下的版本 npm install less2.7.3 npm install less-loader4.0.52./src/config/theme.js文件 module.exports {yellow: {theme-color: #FDCE04},blue: {theme-color: #547CE7} }在sass中使用theme配置的颜色主题&#xff0c;无需引入&#xff0c;直接可…...

android RelativeLayout布局

<?xml version"1.0" encoding"utf-8"?> <RelativeLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"match_parent"android:gravity&…...