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

框架的前置学习-反射

  • 运行java代码要经历的三个阶段

    在这里插入图片描述

  • 反射,程序框架设计的灵魂,将类的各个组成部分封装成其他对象,这就是反射机制。

  • 框架:半成品的软件,在框架的基础上进行开发,可以简化编码

  • 反射的好处:

    1. 可以在程序运行的过程中,操作这些对象
    2. 可以解耦,提高程序的可拓展性
  • 在运行状态中:

    1. 对于任意一个类,都能够知道这个类的所有属性和方法
    2. 对于任意一个对象,都能够调用它的任意属性和方法
  • 与反射机制相关的类

    1. Java.lang.class :代表整个类编译得到的class文件(字节码)
    2. Java.lang.reflect.Method :代表字节码中的方法字节码
    3. Java.lang.reflect.Constructor :代表字节码中的构造器字节码
    4. Java.lang.reflect.Field :代表字节码中的属性字节码
  • 要操作一个字节码,首先要得到这个类的字节码,下面是三种得到字节码的方式

    1. static Class.forName(String className) 这里的className需要时类的全路径,这是一个静态方法

      public class reflect1 {public static void main(String[] args) throws ClassNotFoundException {//第一种方式Class c1=Class.forName("java.lang.String");System.out.println(c1);}
      }
    2. java中的任意一个对象.getClass() ,这个方法继承自Object

      public class reflect1 {public static void main(String[] args) throws ClassNotFoundException {//第一种方式Class c1=Class.forName("java.lang.String");System.out.println(c1);//第二种方式String s="hello";Class c2=s.getClass();System.out.println(c2);}
      }
    3. java语言中的任意一种类型,包括基本数据类型,都有.class属性。

      public class reflect1 {public static void main(String[] args) throws ClassNotFoundException {//第一种方式Class c1=Class.forName("java.lang.String");System.out.println(c1);//第二种方式String s="hello";Class c2=s.getClass();System.out.println(c2);//第三种方式Class c3=String.class;System.out.println(c3);}
      }
    4. JVM在加载一个类的时候,会把这个类的.class字节码文件放在方法区中,栈中放入main方法进行压栈,堆中new出对象c,但是无论使用什么方法获取字节码,一样的class字节码文件只会放一份在方法区中,得到的c变量都是指向方法区中的同一份.class文件。

  • 使用反射机制来实例化对象

  1. 通过Class的newInstance() 方法可以实例化对象

  2. 但是newInstance()方法内部实际上调用了无参构造方法,必须要保证无参构造的存在才可以

        private static void test2() throws InstantiationException, IllegalAccessException {Object o=Student.class.newInstance();System.out.println(o);}
    
  • 反射机制的灵活性,在不修改源码的情况下,可以做到不同对象的实例化,符合OCP开闭原则:对拓展开放,对修改关闭.

    1. 下面的代码中首先利用FileReader读取配置文件,配置文件里面保存了键和值,值是类名,之后new了一个Properties对象,Properties对象的键和值都是String类型,是一种Map数据类型,之后将文件流对象传入Properties对象,再根据键得到值,然后利用反射机制传入类名新建一个对象,实现了对象的灵活创建。
        private static void test3() throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException {FileReader fr=new FileReader("Student.properties");Properties pro=new Properties();pro.load(fr);fr.close();String forName=pro.getProperty("Student");Class C=Class.forName(forName);Object o=C.newInstance();System.out.println(o);}
    
  • 如果只想要让类里面的某些代码被执行,那么可以使用静态代码和Class.forName,像下面的代码那样,每次类加载器加载一个类的时候,就会先执行静态代码块,使用Class.forName而不用创建类的实例化变量

    public class reflect1 {static {System.out.println("静态代码执行!");}
    }
    
        private static void test4() {try {Class.forName("reflect1");} catch (ClassNotFoundException e) {throw new RuntimeException(e);}}
    
  • 获取文件的类路径,可以通过类加载器获取,具体如下:

        private static void test4() {String path=Thread.currentThread().getContextClassLoader().getResource("a.txt").getPath();System.out.println(path);}
    
  • 资源绑定器

    1. 用来获取属性配置文件中的内容

    2. 属性配置文件必须要放在类路径下(src下面)

    3. 必须是properties后缀

    4. 绑定某个属性配置文件的时候,只需要填写配置文件的名字,不需要写后缀,也不能写后缀

          private static void test4() {ResourceBundle bundle=ResourceBundle.getBundle("Student");String path=bundle.getString("Student");System.out.println(path);}
      
  • 获取并操作属性字节码

    1. 首先获取整个字节码

    2. 利用字节码的getFields可以获取到public修饰的所有属性

    3. 利用字节码的getDeclaredFields可以获取到所有属性,无论什么修饰符都可以获取到

    4. 遍历属性列表

    5. 通过属性.getName()可以获取到属性的名字

    6. 通过属性.getType()可以获取到属性的完整类型,getSimpleName是获取简化的类名

    7. 通过属性.getModifiers()可以获取到属性的修饰符id,通过Modifier.toString(id)就可以拿到完整的修饰符

      import java.io.Serializable;public class Student implements Serializable {
      //    属性设置为privateprivate String name;private int age;private static String room;//无参数构造public Student() {}//有参数构造public Student(String name, int age, String room) {this.name = name;this.age = age;this.room=room;}//getter方法public String getName() {return name;}public int getAge() {return age;}public static String getRoom() {return room;}//setter方法public void setName(String name) {this.name = name;}public void setAge(int age) {this.age = age;}public static void setRoom(String room) {Student.room = room;}//重写equals方法public boolean equals(Object obj){if(obj instanceof Student) {//首先将得到的Object转为Student,否则使用不了Student特有的方法(多态的弊端)Student t = (Student) obj;return t.getAge() == this.getAge() && t.getName() == this.getName() && t.getRoom() == this.getRoom();}return false;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}
      }
          private static void test5() throws ClassNotFoundException {//获取整个类Class studentClass=Student.class;//获取public修饰的属性,一个Filed包括private static String room;Field[] fileds=studentClass.getFields();for (Field filed : fileds) {System.out.println(filed);}//获取所有的属性,一个Filed包括private static String room;fileds=studentClass.getDeclaredFields();for (Field filed : fileds) {//获取属性的名字System.out.println("属性的名字:");System.out.println(filed.getName());//获取属性的类型Class filedTypeClass=filed.getType();//getName是获取完整类型,getSimpleName是获取简化的类名String filedType=filedTypeClass.getSimpleName();System.out.println("属性的类型");System.out.println(filedType);//获取属性的修饰符int modify=filed.getModifiers();String modifyName= Modifier.toString(modify);System.out.println("属性的修饰符");System.out.println(modifyName);System.out.println("==================");}}
      
  • 利用反射机制访问一个对象的属性

    1. 要使用反射,当然要先获取一个类的字节码文件

    2. 利用获取到的字节码文件,再用newInstance方法创建一个对象(使用反射的类必须有无参构造)

    3. 利用字节码文件获取这个类的某个属性

    4. 利用这个属性给创建的对象的对应的属性赋值

    5. 在设置对象的属性值之前,需要在使用 set 方法之前,调用 setAccessible(true) 方法来取消对字段的访问权限检查。否则, 会报IllegalAccessException 异常。这是因为 name 字段被声明为 private,无法直接访问。但是使用反射机制绕过访问权限限制可能会导致安全问题。

          private static void test6() throws NoSuchFieldException, InstantiationException, IllegalAccessException {//获取整个类Class studentClass=Student.class;Field filed=studentClass.getDeclaredField("name");Object obj=studentClass.newInstance();filed.setAccessible(true); // 取消对字段的访问权限检查filed.set(obj,"zs");System.out.println(obj);}
      
  • 利用反射机制获取Method

    1. 获取整个类的字节码文件

    2. 通过字节码文件得到方法的字节码,并且遍历它

    3. 通过.getName()获取方法名字

    4. 通过.getReturnType().getSimpleName()获取返回值类型

    5. 通过.getModifiers()获取修饰符id,然后通过Modifier.toString(id)得到修饰符

    6. 通过.getParameterTypes()得到修饰符列表,遍历这个列表,通过.getSimpleName()得到参数名称

          private static void test7() {Class studentClass=Student.class;Method[] methods=studentClass.getDeclaredMethods();for (Method method : methods) {//获取方法名System.out.println("方法名");System.out.println(method.getName());//获取方法的返回值类型System.out.println("方法的返回值类型");System.out.println(method.getReturnType().getSimpleName());//获取修饰符列表System.out.println("方法的修饰符列表");System.out.println(Modifier.toString(method.getModifiers()));//方法的参数列表System.out.println("方法的参数列表");Class[] parametorType= method.getParameterTypes();for (Class aClass : parametorType) {System.out.println(aClass.getSimpleName());}System.out.println("========================");}}
      
  • 通过反射机制操纵Method

    1. 首先获取字节码

    2. 利用得到的字节码新建一个对象

    3. 利用得到的字节码获取一个指定的方法,在java里面,由于存在方法的重载,所以区分一个方法是由方法名+方法参数类型,而不仅仅是方法名,所以使用getDeclaredMethod方法需要一个方法名和若干参数的class

    4. 最后使用这个方法的invoke方法,传入要操纵的对象和实参

          private static void test8() throws InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {Class studentClass=Student.class;Object obj=studentClass.newInstance();Method setName=studentClass.getDeclaredMethod("setName",String.class);Object returnVa=setName.invoke(obj,"zs");System.out.println(obj);}
      
  • 通过反射机制获取构造方法

    1. 获取整个类的字节码文件

    2. 通过字节码文件得到构造方法的字节码,并且遍历它

    3. 通过.getName()获取方法名字

    4. 通过.getModifiers()获取修饰符id,然后通过Modifier.toString(id)得到修饰符

    5. 通过.getParameterTypes()得到修饰符列表,遍历这个列表,通过.getSimpleName()得到参数名称

          private static void test9() {Class studentClass=Student.class;Constructor[] constructors=studentClass.getDeclaredConstructors();for (Constructor constructor : constructors) {//获取构造方法名System.out.println("构造方法名");System.out.println(constructor.getName());//获取修饰符列表System.out.println("构造方法的修饰符列表");System.out.println(Modifier.toString(constructor.getModifiers()));//方法的参数列表System.out.println("构造方法的参数列表");Class[] parametorType= constructor.getParameterTypes();for (Class aClass : parametorType) {System.out.println(aClass.getSimpleName());}System.out.println("========================");}}
      
  • 使用反射机制的构造方法创建对象

    1. 直接利用字节码创建(已过时)

    2. 首先获取无参构造函数,然后调用无参构造函数

    3. 首先获取有参构造函数,然后调用有参构造函数

          private static void test10() throws InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {//使用反射创建对象//1. 直接利用字节码创建Class studentClass=Student.class;Object t1=studentClass.newInstance();//2. 先利用字节码获取构造函数,然后再利用构造函数创建对象//首先是无参构造Constructor con1=studentClass.getDeclaredConstructor();Object t2=con1.newInstance();//最后是有参构造方法Constructor con2=studentClass.getDeclaredConstructor(String.class,int.class,String.class);Object t3=con2.newInstance("zs",18,"h111");System.out.println(t1);System.out.println(t2);System.out.println(t3);}
      
  • 使用反射获取一个类的父类以及接口

        private static void test11() {Class stringClass=String.class;//获取String的父类Class superClass=stringClass.getSuperclass();System.out.println("父类是");System.out.println(superClass.getSimpleName());//获取接口Class[] interface1=stringClass.getInterfaces();System.out.println("接口是");for (Class aClass : interface1) {System.out.println(aClass.getSimpleName());}}
    

相关文章:

框架的前置学习-反射

运行java代码要经历的三个阶段 反射,程序框架设计的灵魂,将类的各个组成部分封装成其他对象,这就是反射机制。 框架:半成品的软件,在框架的基础上进行开发,可以简化编码 反射的好处: 可以在…...

【使用bat脚本实现批量创建文件夹、批量复制文件至对应文件夹中】

使用bat脚本实现批量创建文件夹、批量复制文件至对应文件夹中 常用cmd命令 场景一:在指定位置批量创建文件夹 在桌面创建一个txt文件编写创建目录代码 //在桌面"五保户结算单"的文件夹下创建名称为"1张三"的文件夹 md E:\桌面\五保户结算单\…...

面向视频会议场景的 H.266/VVC 码率控制算法研究

文章目录 面向视频会议场景的 H.266/VVC 码率控制算法研究个人总结摘要为什么要码率控制码率控制的关键会议类视频码率控制研究背景视频会议系统研究现状目前基于 R-λ模型的码率控制算法的问题文章主要两大优化算法优化算法1:基于视频内容相关特征值的码率控制算法…...

【网络基础实战之路】设计网络划分的实战详解

系列文章传送门: 【网络基础实战之路】设计网络划分的实战详解 【网络基础实战之路】一文弄懂TCP的三次握手与四次断开 【网络基础实战之路】基于MGRE多点协议的实战详解 【网络基础实战之路】基于OSPF协议建立两个MGRE网络的实验详解 PS:本要求基于…...

MacBook触控板窗口管理 Swish for Mac

Swish for Mac是一款用于通过手势来控制mac应用窗口的软件,你可以通过这款软件在触控板上进行手势控制,你可以在使用前预设好不同手势的功能,然后就能直接通过这些手势让窗口按照你想要的方式进行变动了 Swish 支持 Haptick Feedback 震动反…...

VS开发Qt程序,无法打印QDebug调试信息,VS进行Qt开发时Qt Designer无法使用“转到槽”选项

VS开发Qt程序,无法打印QDebug调试信息,VS进行Qt开发时Qt Designer无法使用“转到槽”选项 VS开发Qt程序,无法打印QDebug调试信息VS进行Qt开发时Qt Designer无法使用“转到槽”选项 VS开发Qt程序,无法打印QDebug调试信息 解决方案…...

MySQL操作命令详解:增删改查

文章目录 一、CRUD1.1 数据库操作1.2 表操作1.2.1 五大约束1.2.2 创建表1.2.3 修改表1.2.3 删除表1.2.4 表数据的增删改查1.2.5 去重方式 二、高级查询2.1 基础查询2.2 条件查询2.3 范围查询2.4 判空查询2.5 模糊查询2.6 分页查询2.7 查询后排序2.8 聚合查询2.9 分组查询2.10 联…...

MySQL字段类型与存储空间的关系

在 MySQL 中,对于整数类型(如 INT)、字符类型(如 VARCHAR)、浮点数类型(如 DOUBLE)等,参数(括号中的数字或长度)通常用于限制数据的范围或精度,但…...

红船元宇宙 上海布袋除尘器后一家太平洋百货月底停业

上海布袋除尘器后一家太平洋百货即将停业。 7月31日,上海太平洋百货微信公号发布公告称,由于与合资方的合作期限今年届满,上海太平洋百货徐汇店将于2023年8月31日营业结束后正式谢幕,终止经营,并于即日起开展大型主题感…...

vue 图片回显标签

第一种 <el-form-item label"打款银行回单"><image-preview :src"form.bankreceiptUrl" :width"120" :height"120"/></el-form-item>// 值为 https://t11.baidu.com/it/app106&fJPEG&fm30&fmtauto&…...

《向量数据库指南》——使用SQuAD 数据集演示Faiss 功能

使用 SQuAD 数据集进行演示 现在,我们可以通过示例演示了解 Faiss 功能。本次示例中,将使用斯坦福的问答数据集(SQuAD)。SQuAD 是一个常用的自然语言处理(NLP)数据集,该数据集基于用户在百科中提出的问题,每个问题的答案都来自于对应阅读段落的一段文本,共计 500 多…...

java多线程并发面试题总结(史上最全40道)

1、多线程有什么用&#xff1f; 一个可能在很多人看来很扯淡的一个问题&#xff1a;我会用多线程就好了&#xff0c;还管它有什么用&#xff1f;在我看来&#xff0c;这个回答更扯淡。所谓"知其然知其所以然"&#xff0c;"会用"只是"知其然"&am…...

IDEA强大的VisualGC插件

前言 开发阶段实时监测&#xff0c;自己的JVM信息&#xff0c;实时可视化 Hotspot JVM 垃圾回收监控工具, 支持查看本地和远程JVM进程, 支持G1 and ZGC算法。 插件安装 在线安装 IntelliJ IDEA 可通过在线安装的方式&#xff0c;安装插件 JDK VisualGC&#xff0c;安装步骤: …...

桐乡上元教育室内设计培训班-CAD学习

室内设计四大软件】 1、Auto ca?‌‌?‌‌d&#xff1a;着重培训建筑与室内设计所用知识&#xff0c;增强实践性施工图纸的绘制与操作速度; 课程包括&#xff1a;CAD基本命令与修改器;室内平面图、地面、天花、照明等图;室内立面图绘制;室内剖面图绘制;定植尅家具的平面、立…...

h5浏览pdf文件

将hybrid整个复制到一级文件夹下 hybrid地址&#xff1a;https://download.csdn.net/download/qq_37194189/88157330 创建一个 pdf页面用于展示pdf文件 <template><view style"width: 100%;" ><web-view :src"pdfUrl"></web-view&…...

无涯教程-Lua - 嵌套if语句函数

在Lua编程中&#xff0c;您可以在另一个if or else if语句中使用一个if or else if语句。 nested if statements - 语法 嵌套if 语句的语法如下- if( boolean_expression 1) then--[ Executes when the boolean expression 1 is true --]if(boolean_expression 2)then--[ Ex…...

vue v-slot指令

目录 定义语法使用场景场景一场景二场景三tips只有一个默认插槽时 定义 在Vue中&#xff0c; v-slot 指令用于定义插槽的模板内容。它用于在父组件中传递内容到子组件中的插槽。 v-slot 指令可以用于 标签或组件标签上&#xff0c;以便在子组件中使用插槽。 语法 使用 v-slo…...

【机器学习】西瓜书学习心得及课后习题参考答案—第6章支持向量机

笔记心得 6.1 间隔与支持向量—— w w w是法向量&#xff0c;垂直与超平面 w T x b 0 w^Txb0 wTxb0。这一节了解了支持向量机的基本型。 min ⁡ w , b 1 2 ∣ ∣ w ∣ ∣ 2 s . t . y i ( w T x i b ) ≥ 1 , i 1 , 2 , . . . , m . \min_{w,b} \frac{1}{2}||w||^2 \\ s.…...

无涯教程-Perl - 面向对象

Perl中的面向对象概念很大程度上基于引用以及匿名数组和哈希。让我们开始学习面向对象Perl的基本概念。 定义类 在Perl中定义一个类非常简单。类以最简单的形式对应于Perl软件包。要在Perl中创建一个类&#xff0c;我们首先构建一个包。 Perl软件包在Perl程序中提供了一个单…...

Linux安装VScode

从本篇开始&#xff0c;打算有时间就写写在VScode中编写一些ros相关的案例程序用于学习记录。本篇是如何在Linux安装VScode的第一篇。 一、下载VScode 在Linux中打开浏览器输入&#xff1a;https://code.visualstudio.com/Download&#xff0c;选择与你电脑相匹配的版本下载&…...

vscode里如何用git

打开vs终端执行如下&#xff1a; 1 初始化 Git 仓库&#xff08;如果尚未初始化&#xff09; git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...

【单片机期末】单片机系统设计

主要内容&#xff1a;系统状态机&#xff0c;系统时基&#xff0c;系统需求分析&#xff0c;系统构建&#xff0c;系统状态流图 一、题目要求 二、绘制系统状态流图 题目&#xff1a;根据上述描述绘制系统状态流图&#xff0c;注明状态转移条件及方向。 三、利用定时器产生时…...

ServerTrust 并非唯一

NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...

从零实现STL哈希容器:unordered_map/unordered_set封装详解

本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说&#xff0c;直接开始吧&#xff01; 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...

拉力测试cuda pytorch 把 4070显卡拉满

import torch import timedef stress_test_gpu(matrix_size16384, duration300):"""对GPU进行压力测试&#xff0c;通过持续的矩阵乘法来最大化GPU利用率参数:matrix_size: 矩阵维度大小&#xff0c;增大可提高计算复杂度duration: 测试持续时间&#xff08;秒&…...

Web 架构之 CDN 加速原理与落地实践

文章目录 一、思维导图二、正文内容&#xff08;一&#xff09;CDN 基础概念1. 定义2. 组成部分 &#xff08;二&#xff09;CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 &#xff08;三&#xff09;CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 &#xf…...

以光量子为例,详解量子获取方式

光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学&#xff08;silicon photonics&#xff09;的光波导&#xff08;optical waveguide&#xff09;芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中&#xff0c;光既是波又是粒子。光子本…...

基于 TAPD 进行项目管理

起因 自己写了个小工具&#xff0c;仓库用的Github。之前在用markdown进行需求管理&#xff0c;现在随着功能的增加&#xff0c;感觉有点难以管理了&#xff0c;所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD&#xff0c;需要提供一个企业名新建一个项目&#…...

IP如何挑?2025年海外专线IP如何购买?

你花了时间和预算买了IP&#xff0c;结果IP质量不佳&#xff0c;项目效率低下不说&#xff0c;还可能带来莫名的网络问题&#xff0c;是不是太闹心了&#xff1f;尤其是在面对海外专线IP时&#xff0c;到底怎么才能买到适合自己的呢&#xff1f;所以&#xff0c;挑IP绝对是个技…...

C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)

名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...