【数据结构】反射,枚举你必须知道的相关知识

news2024/11/15 4:03:07

前言:

🌟🌟本期讲解关于反射以及枚举,希望能帮到屏幕前的你。

🌈上期博客在这里:http://t.csdnimg.cn/7D225

🌈感兴趣的小伙伴看一看小编主页:GGBondlctrl-CSDN博客

目录

📚️1.反射

1.1反射的定义

1.2反射的用途

1.3反射的相关类

1.4class类(放射机制的起源)

1.5Class类的相关的方法:

1.6获取反射对象的三种方法 

1.7反射的总结 

 📚️2.枚举

2.1背景以及定义

2.2枚举的常用方法

2.3枚举的总结 

 📚️3.反射和枚举的关系

 📚️4.总结


📚️1.反射

1.1反射的定义

对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性,既然能拿到那么,我们就可以修改部分类型信息;

这种动态获取信息以及动态调用对象方法的功能称为java语言的反射(reflection)机制

1.2反射的用途

小编这里总结:

1.对于某些类中,存在私有的变量或者方法只能供自己类或者系统使用,我们就可以使用Java反射机制获取这些私有的属性,方法。

2. 反射最重要的用途就是开发各种通用框架。

1.3反射的相关类

1.4class类(放射机制的起源)

Java文件被编译后,生成了.class文件,JVM此时就要去解读.class文件 ,被编译后的Java件.class也被JVM解析为一个对象,这个对象就是 java.lang.Class .这样当程序在运行时,每个jav文件就最终变成了Class类对象的一个实例

1.5Class类的相关的方法:

1.获得类的相关方法:

代码实例:

 Class<?> c1 = Class.forName("Fmlambda.Student"); //拿到对象
 Student student = (Student) c1.newInstance();  //进行实例化

这里小编列举了两个列子

2.获得类中属性的相关方法:

getField(String name)
获得某个公有的属性对象
getFields()
获得所有公有的属性对象
getDeclaredField(String name)
获得某个属性对象
getDeclaredFields()
获得所有属性对象

代码实例:

 public static void reflectPrivateField() {
        try {
            Class<?> c3 = Class.forName("Fmlambda.Student");
            Field field = c3.getDeclaredField("name");
            field.setAccessible(true);
            Student student = (Student) c3.newInstance();
            field.set(student, "idontlovejava");
            System.out.println(student);
        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

注解:拿到反射的类的Class对象,并且获取这个名字私有属性对象,由于name为私有属性所以得“授权”,然后进行实例化,改变这个私有属性对象的内容,最后实现打印。

3.获得类中构造器相关的方法 :

 代码实例:

public static void reflectPrivateConstructor() {
        try {
            Class<?> c2 = Class.forName("Fmlambda.Student");
            Constructor<?> constructor = c2.getDeclaredConstructor(String.class, int.class);
            constructor.setAccessible(true);
            Student student = (Student) constructor.newInstance("ilovejava", 20);
            System.out.println(student);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException();
        } catch (InstantiationException e) {
            throw new RuntimeException();
        } catch (InvocationTargetException e) {
            throw new RuntimeException();
        } catch (IllegalAccessException e) {
            throw new RuntimeException();
        } catch (ClassNotFoundException e) {
            throw new RuntimeException();
        }
    }

注解:拿到反射的类的Class对象,并且获取这个类中与参数匹配的构造方法,由于为私有属性所以得“授权”,然后进行实例化,改变这个私有构造方法的内容,最后实现打印。

4.获得类中方法相关的方法: 

getMethod(String name, Class...<?> parameterTypes)
获得该类某个公有的方法
getMethods()
获得该类所有公有的方法
getDeclaredMethod(String name, Class...<?> parameterTypes)
获得该类某个方法
getDeclaredMethods()
获得该类所有方法

代码实例:

public static void reflectPrivateMethod() {
        Class<?> c4 = null;
        try {
            c4 = Class.forName("Fmlambda.Student");
            Method method = c4.getDeclaredMethod("function", String.class);
            method.setAccessible(true);
            Student student = (Student) c4.newInstance();

            method.invoke(student, "我是一个参数....");
            System.out.println();
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        }
    }
}

注解:拿到反射的类的Class对象,并且获取这个类中的某个私有方法,进行参数匹配,由于为私有属性所以得“授权”,然后进行实例化,改变这个私有方法的内容,最后实现打印。

1.6获取反射对象的三种方法 

第一种 ,使用 Class.forName(" 类的全路径名 "); 静态方法。
前提:已明确类的全路径名。
第二种 ,使用 .class 方法。
说明:仅适合在编译前就已经明确要操作的 Class
第三种 ,使用类对象的 getClass() 方法

代码演示:

 public static void main(String[] args) {
        //1.通过调用getclass
        Student student = new Student();
        Class c = student.getClass();
        //2.直接通过 类名.class 的方式得到,该方法最为安全可靠,程序性能更高
        //这说明任何一个类都有一个隐含的静态成员变量 class
        Class c1 = Student.class;
        //3、通过 Class 对象的 forName() 静态方法来获取,用的最多,
        //但可能抛出 ClassNotFoundException 异常
        Class c2 = null;
        try {
            c2 = Class.forName("Fmlambda.Student");
        } catch (ClassNotFoundException e) {
            throw new RuntimeException();
        }

注意:使用forName时要抛出异常,要通过try-catch来进行捕获,并进行抛出异常。这里小编加了注解大家可以通过注解来进行查看。

1.7反射的总结 

优点:

1. 对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法
2. 增加程序的灵活性和扩展性,降低耦合性,提高自适应能力
3. 反射已经运用在了很多流行框架如:Struts、Hibernate、Spring 等等。

缺点:

1. 使用反射会有效率问题。会导致程序效率降低
2. 反射技术绕过了源代码的技术,因而会带来维护问题。反射代码比相应的直接代码更复杂 

 📚️2.枚举

2.1背景以及定义

枚举是在 JDK1.5 以后引入的。主要用途是:将一组常量组织起来,在这之前表示一组常量通常使用定义常量的方式

 常量举例有不好的地方,例如:可能碰巧有个数字1,但是他有可能误会为是RED,现在我们可以直接用枚举来进行组织,这样一来,就拥有了类型,枚举类型。而不是普通的整形1.

代码如下:

public static final int RED = 1;
public static final int GREEN = 2;
public static final int BLACK = 3;
//改为枚举类型后
public enum TestEnum {
RED,BLACK,GREEN;
}

2.2枚举的常用方法

values()
以数组形式返回枚举类型的所有成员
ordinal()
获取枚举成员的索引位置
valueOf()
将普通字符串转换为枚举实例
compareTo()
比较两个枚举成员在定义时的顺序

代码实现:

public enum Textdemo {
    RED(0,"红色"),WHITE(1,"WHITE"),
    GREEN(2,"GREEN"),BLACK(3,"BLACK");

    public int ordinal;
    public String color;

    Textdemo(int ordinal, String color) {
        this.ordinal = ordinal;
        this.color = color;
    }
    public static void main(String[] args) {
        Textdemo[] textdemos=Textdemo.values();  //以数组的形式返回枚举实例
        for (int i = 0; i <textdemos.length ; i++) {
            System.out.println(textdemos[i]+"索引位置是"+textdemos[i].ordinal());//进行枚举索引的打印
        }
        Textdemo textdemo=Textdemo.valueOf("RED");  //将字符串转化为枚举实例
        System.out.println(textdemo.color);
        System.out.println(WHITE.compareTo(BLACK));  //比较两个枚举在定义时的位置
       

    }

注意:这里的字符串转化为枚举时需要这个字符串时已经被定义了的枚举类型,否则就会报错。这里小编在每个方法之后都加了注解,大家可以按照注解来进行学习。

 注意:枚举的构造方法为私有方法,在编写构造方法时,为私有权限符,但是这里可以进行省略

2.3枚举的总结 

优点:

枚举常量更加简单和安全

枚举具有内置接口,代码更加简洁优美

缺点:

无法进行继承,不能进行扩展

 📚️3.反射和枚举的关系

在上述讲解中,我们知道了关于反射机制,又由于枚举的构造方法是私有的,那么我们可以通过反射来拿到枚举的实例对象呢?

此时就有如下代码:

 public static void reflectconstruct() {

        try {
            Class<?> c1 = Class.forName("Fmlambda.Textdemo");
            
            Constructor<?> constructor = c1.getDeclaredConstructor( int.class, String.class);
            constructor.setAccessible(true);
            Textdemo textdemo = (Textdemo) constructor.newInstance(5, "紫色");
            System.out.println(textdemo);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        }

    }

此时就会发现代码报错了!!!

此时可以看到没有构造方法!!!

解释:

我们所有的枚举类,都是默认继承与 java.lang.Enum ,说到继承,继承了什么?继承了父类除构造函数外的所有东西,并且子类要帮助父类进行构造而我们写的类,并没有帮助父类构造!

枚举的内部原码构造方法:

protected Enum(String name, int ordinal) {
this.name = name;
this.ordinal = ordinal;
}

 此时我们发现父类还有两个参数没有进行子类帮助构造

所以改正后代码如下:

 constructor = c1.getDeclaredConstructor(String.class, int.class, int.class, String.class);

只用该这一行代码即可,那么此时就可以发现又报错啦~~~~

 

所以这就是源码的问题了:

源码图示:

 

这里说明的清清楚楚,就是说不能通过反射获取枚举实例,所以一切真相大白!!! 

 所以总结:枚举已经被Java的反射机制给过滤了~~~,所以枚举可以避免反射和序列化的问题。

 📚️4.总结

💬💬本期小编讲解了关于反射,枚举的相关使用方法,并且附加代码实现讲解,最后通过源码解析总结了反射和枚举之间的关系。

🌅🌅🌅~~~~最后希望与诸君共勉,共同进步!!!


                              💪💪💪以上就是本期内容了, 感兴趣的话,就关注小编吧。

                                                         😊😊  期待你的关注~~~

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

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

相关文章

获得并修改硬件序列号--CPU、主板、内存、硬盘等(有源码)

大家都知道很多Anti Cheat会封硬件序列号&#xff0c;所以本文探索一下如何get and modify序列号。 这个服务是比较贵的: 于是有了研究一下的想法。 思路: 1. 通过厂商自带的程序刷新固件。 2. 自己写驱动修改。 思路1不讨论&#xff0c;要拿到厂商去修改&#xff0c;很不方…

台球助教陪练预约系统源码开发

随着科技的发展和人们对生活质量要求的提高&#xff0c;体育运动的数字化趋势日益明显。台球作为一种集休闲娱乐与竞技于一体的运动项目&#xff0c;在全球范围内拥有广泛的爱好者群体。为了更好地满足这部分人群的需求&#xff0c;开发一个高效的台球助教陪练预约系统变得尤为…

国家超算互联网入选国家数据局“全国一体化算力网应用优秀案例”

在2024年8月29日举行的中国国际大数据产业博览会上&#xff0c;国家数据局公布了首批“全国一体化算力网应用优秀案例”。 这一举措是在经过严格的评审过程后&#xff0c;挑选了包括“国家超算互联网”在内的25个创新平台和方案&#xff0c;它们代表了当前算力网建设的先进与创…

【ssh】环境问题汇总

问题1.同时显示两个不同的 Conda 环境&#xff0c;如图 (base) 环境 是 Conda 安装后默认激活的环境。 (ani) 是手动创建的另一个 Conda 环境。 解决&#xff1a;执行conda deactivate。如果 (ani) 环境多次激活&#xff0c;需要多次执行 conda deactivate 才能回到 base 环境…

【论文分享】sNPU: Trusted Execution Environments on Integrated NPUs 24‘ISCA

目录 AbstractINTRODUCTIONBACKGROUND AND RELATED WORKTrusted Execution Environment (TEE)Neural Processing Unit (NPU)Integrated NPU v.s. Discrete NPU Multi-tasking Requirements for NPUsLow NPU utilization for a single ML workloadSimultaneous execution of bot…

jquery swiper插件的用法

一、Swiper插件简介 Swiper是一个纯JavaScript打造的滑动特效插件&#xff0c;面向手机、平板电脑等移动终端&#xff0c;同时也支持桌面浏览器。Swiper开源、免费、稳定、使用简单且功能强大&#xff0c;是架构移动终端网站的重要选择。 它支持触摸滑动、响应式设计、循环滑动…

基于Java+SpringBoot+Vue+MySQL的地方美食分享网站

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 基于SpringBootVue的地方美食分享网站【附源码文档】、前后…

NXP i.MX8系列平台开发讲解 - 4.1.3 GPSD 使用

专栏文章目录传送门&#xff1a;返回专栏目录 Hi, 我是你们的老朋友&#xff0c;主要专注于嵌入式软件开发&#xff0c;有兴趣不要忘记点击关注【码思途远】 文章目录 关注星号公众号&#xff0c;不容错过精彩 作者&#xff1a;HywelStar 目录 1. 认识GPSD 2. 安装GPSD 2.…

哪些好用的待办事项清单值得推荐:待办任务清单app

在现代快节奏的生活中&#xff0c;我们每个人都面临着大量的待办事项。无论是工作中的紧急任务&#xff0c;还是生活中的琐碎事务&#xff0c;这些事情常常让我们感到应接不暇。为了更好地管理这些待办事项&#xff0c;将它们列成清单&#xff0c;并设置明确的完成时间节点&…

2024年9月3日嵌入式学习

数据结构 1定义 一组用来保存一种或者多种特定关系的数据的集合&#xff08;组织和存储数据&#xff09; 程序的设计&#xff1a;将现实中大量而复杂的问题以特定的数据类型和特定的存储结构存储在内存中&#xff0c; 并在此基础上实现某个特定的功能的操作&am…

数据结构(6.4_5)——有向无环图

有向无环图&#xff1a;若一个有向图中不存在环&#xff0c;则称为有向无环图&#xff0c;简称DAG图(Directed Acyclic Graph) DAG描述表达式 普通表达式&#xff1a; DAG描述表达式&#xff1a;解题方法&#xff1a; 练习 总

初始MYSQL数据库(2)——创建、查询、更新、删除数据表的相关操作

找往期文章包括但不限于本期文章中不懂的知识点&#xff1a; 个人主页&#xff1a;我要学编程(ಥ_ಥ)-CSDN博客 所属专栏&#xff1a; MYSQL 前面我们学习了创建、删除数据库以及创建、查看、删除数据表的相关操作。 我们知道数据库中所存储的数据其实就是数据表中一条一条的记…

eval 函数 >>>> 变量 = eval (字符串)

作用&#xff1a; 去掉引号并会进行数据之间的加法等运算 eval函数与input的使用 注意eval 后面的括号中必须是字符串&#xff08;加了引号的&#xff09;&#xff0c;不能直接跟字符串

vue在生产环境和测试环境去掉 console 打印日志 只保留 “error“、 “warn“

vue在生产环境和测试环境去掉 console 打印日志 只保留 “error”、 “warn” 文章目录 vue在生产环境和测试环境去掉 console 打印日志 只保留 "error"、 "warn"一、安装插件二、babel.config.js配置 一、安装插件 npm install babel-plugin-transform-r…

Python的VSCode配置

主要参考&#xff1a; 使用vscode编写、运行Python程序_vscode写python-CSDN博客 这篇文章主要记录在vscode中编写、运行Python程序的方法&#xff0c;以便于后面的学习。 这里我是在win10里完成的&#xff0c;在Ubuntu中的配置方法与之类似。 如果你也在Win10下完成&#xff0…

Leetcode - 138双周赛

目录 一&#xff0c;3270. 求出数字答案 二&#xff0c;3271. 哈希分割字符串 三&#xff0c;3272. 统计好整数的数目 四&#xff0c;3273. 对 Bob 造成的最少伤害 一&#xff0c;3270. 求出数字答案 本题数据范围小&#xff0c;可以将数字转换成字符串来做&#xff0c;这里…

【科研绘图】【3D轨线图】:附Origin详细画图流程

目录 No.1 理解3D轨线图 No.2 画图流程 1 导入数据并绘图 2 设置绘图细节 3 设置坐标轴 4 效果图 No.1 理解3D轨线图 3D轨线图&#xff0c;是指在三维坐标系中&#xff0c;通过连续的点或线段连接而成的图形&#xff0c;用于表示一个或多个物体在三维空间中的运动路径。…

AT3340:支持BDS/GPS双模授时板数据手册

AT3340采用ATGM331C-5T31授时模块&#xff0c;是高授时精度的BDS/GPS双模接收机板卡&#xff0c;包含32个跟踪通道&#xff0c;支持GPS和BDS的单系统授时定位和双系统联合授时定位&#xff0c;可以通过上位机命令切换。其中的射频前端芯片和基带芯片全部由杭州中科微独立研发&a…

网络地址转换NAT(Network Address Translation)

NAT概述 NAT是将IP数据报文头中的IP地址转换为另一个IP地址的过程&#xff0c;主要用于实现内部网络&#xff08;私有IP地址&#xff09;访问外部网络&#xff08;公有IP地址&#xff09;的功能。Basic NAT是实现一对一的IP地址转换&#xff0c;而NAPT可以实现多个私有IP地址映…

wacat - 一款开源随机测试工具

想象一下&#xff0c;你离开电脑一会儿去拿一杯咖啡。与此同时&#xff0c;你的猫走过键盘&#xff0c;引发了一些混乱。 wacat 应用程序&#xff1a; • 访问你的网页应用的根网址 • 随机访问应用中的每个链接 • 在表单中添加随机文本输入 • 从下拉菜单、复选框等中选择…