反射Reflection

news2024/11/16 19:47:59

目录

  • 1. 反射快速入门
    • 1. 需求
    • 2. 运用反射
  • 2. 反射原理图
    • 2.1 反射相关的主要类
    • 2.1 反射优点和缺点
      • 2.1.1 反射调用优化-关闭访问检查
  • 4. Class类分析
    • 4.1 Class类常用方法
    • 4.2 获取Class类对象【六种】
    • 4.3 哪些类型有class对象
    • 4.4 动态和静态加载
    • 4.5 类加载流程图
  • 5. 获取类结构信息
    • 5.1 获取公有的Field、Method、Constructor
    • 5.1 获取私有的Field、Method、Constructor
    • 5.2 反射爆破构造器【创建实例】
      • 5.2.1 获取公有构造器,利用公有构造器,创建实例
      • 5.2.2 获取私有构造器,对私有构造器进行暴破,创建实例
    • 5.3 反射爆破属性
    • 5.4 反射爆破方法

1. 反射快速入门

1. 需求

根据配置文件 re.properties的信息,创建指定对象并调用指定方法

在这里插入图片描述

2. 运用反射

在这里插入图片描述

2. 反射原理图

  1. 反射机制允许程序在执行期间借助于Reflection API取得任何类的内部信息(比如成员变量、构造器、成员方法等等),并能操作对象的属性及方法, 反射在设计模式和框架底层都会用到;
  2. 加载完类之后,在堆中就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象包含了类的完整结构信息。通过这个对象得到类的结构。这个Class对象就像一面镜子,通过这个镜子看到类的结构,所以,形象地称之为:反射
    在这里插入图片描述

2.1 反射相关的主要类

  1. java.lang.Class: 代表一个类,Class对象表示某个类加载后在堆中的对象
  2. java.lang.reflect.Method: 代表类的方法,Method对象表示某个类的方法
  3. java.lang.reflect.Field: 代表类的成员变量,Field对象表示某个类的成员变量
  4. java.lang.reflect.Constructor: 代表类的构造方法, 表示构造器
    在这里插入图片描述

2.1 反射优点和缺点

优点:可以动态地创建和使用对象,是框架底层核心;
缺点:使用反射基本是解释执行,对执行速度有影响;
在这里插入图片描述

2.1.1 反射调用优化-关闭访问检查

  1. Method和Field,Constructor对象都有setAccessible()方法;
    Field
    在这里插入图片描述
    Method
    在这里插入图片描述
    Constructor
    在这里插入图片描述
    在这里插入图片描述
  2. setAccessible作用是启动和禁用访问安全检查的开关;
  3. 参数为true表示 反射的对象在使用时取消访问检查,提高反射的效率,参数值为false则表示反射的对象执行访问检查;
    在这里插入图片描述

4. Class类分析

  1. Class也是类,因此也继承Object类;
    在这里插入图片描述
  2. Class类对象不是new出来的,而是系统创建的,loadClass类;
    在这里插入图片描述
  3. 对于某个类的Class类对象,在内存中只有一份,因为类只加载一次;
    在这里插入图片描述
  4. 每个类的实例都会记得自己是由哪个Class实例所生成;
  5. 通过Class对象可以完整地得到一个类的完整结构,通过一系列API;
方法名功能说明
static Class forName(String name)返回指定类名 name 的Class对象
Object newInstance()调用缺省构造函数,返回该Class对象的一个实例
getName()返回此Class对象所表示的实体(类、接口、数组类、基本类型等)名称
Class [] getInterfaces()获取当前Class对象的接口
ClassLoader getClassLoader()返回该类的类加载器
Class getSuperclass()返回表示此Class的实体的超类的Class
Constructor[] getConstructor()返回一个包含某些Constructor对象的数组
Field[] getDeclaredFields()返回Field对象的一个数组
Method getMethod(String name…)返回一个Method对象,此对象的形参类型为paramType
  1. Class对象是存放在堆的;
  2. 类的字节码是二进制数据,是放在方法区的,有的地方称为类的元数据;

4.1 Class类常用方法

public class Class02 {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
        String classAllPath = "com.zzw.Car";
        //1. 获取Cat类 对应的Class对象
        //<?> 表示不确定的java类型
        Class<?> cls = Class.forName(classAllPath);
        //2. 输出cls
        System.out.println(cls);//显示cls对象,是哪个类的Class对象,com.zzw.Cat
        System.out.println(cls.getClass());
        //3. 得到包名
        System.out.println("包名:" + cls.getPackage().getName());//包名
        //4. 得到全类名
        System.out.println("全类名:" + cls.getName());
        //5. 通过cls创建对象实例
        Car car = (Car) cls.newInstance();
        System.out.println(car);
        //6. 通过反射获取属性 brand
        Field brand = cls.getField("brand");
        System.out.println(brand.get(car));//宝马
        //7. 通过反射给属性赋值
        brand.set(car, "奔驰");
        System.out.println(brand.get(car));//奔驰
        //8. 得到所有的属性
        Field[] fields = cls.getFields();
        for (Field field : fields) {
            System.out.println(field.getName());
        }
    }
}

4.2 获取Class类对象【六种】

在这里插入图片描述

  1. 已知一个类的全类名,且该类在类路径下,可通过Class类的静态方法forName()获取,可能抛出ClassNotFoundException异常;
    应用场景: 多用于配置文件,读取类全路径,加载类;在底层的xml文件中用的多!
  2. 若已知具体的类,通过类的class获取,该方式最为安全可靠,程序性能最高;
    应用场景: 多用于参数传递
    比如:cls.getConstructor(String.class,int.class)
  3. 对象.getClass()
    应用场景:有对象实例
  4. 通过类加载器来获取类的Class对象在这里插入图片描述
  5. 基本数据类型获得Class类对象
  6. 基本数据类型对应的包装类,通过.TYPE 得到Class类对象
    在这里插入图片描述

4.3 哪些类型有class对象

在这里插入图片描述

4.4 动态和静态加载

反射机制是java实现动态语言的关键,也就是通过反射实现类动态加载;

  1. 静态加载:编译时加载相关的类,如果没有则报错,依赖性太强;
    在这里插入图片描述
    在这里插入图片描述
  2. 动态加载:运行时加载需要的类,如果运行时不用该类,即使不存在该类也不会报错,降低了依赖性;
    在这里插入图片描述
    在这里插入图片描述
  • 类加载时机
    1. 当创建对象时(new);//静态加载
    2. 当子类被加载时,父类也加载;//静态加载
    3. 调用类中的静态成员时;//静态加载
    4. 通过反射;//动态加载

4.5 类加载流程图

在这里插入图片描述

  1. 写源代码,源代码进行编译,得到了它的字节码文件,运行时对字节码文件进行加载,类加载时分了三个阶段:
  2. 先加载Loading、然后连接Linking(连接里面又分成验证(verification)、准备(Preparation)、解析(Resolution) ,验证阶段主要是对文件进行安全的校验,比如文件的格式、源数据验证是否正确、字节码是否正确、符号引用是否正确;准备阶段主要给静态变量分配内存(默认初始化),并且完成静态变量的默认初始化;解析阶段主要功能:虚拟机将常量池中的符号引用替换为直接引用)、初始化是真正执行在类中定义的java代码(比如静态代码块,静态变量的指定显示赋值,)、初始化initialization(指定显示初始化)、
  3. 类加载完成之后,在内存中会产生两个重要的部分,一个在方法区里面,它会把字节码以二进制的形式保存起来,同时,在堆区,还会生成字节码对应的数据结构,其实就是我们所说的类的Class对象,方法区和堆区之间还有个引用,那么它们之间就体现了一个反射机制。
  4. 总结:类加载阶段分为了五个小步骤,类加载后内存的布局就是在方法区生成了类的字节码二进制数据,这个就是源数据;而堆区里面生成的类的Class对象,就是一些数据结构,是数据的访问入口。
  • 4.5.1 类加载各阶段完成任务
    在这里插入图片描述
    在类加载的三个阶段里面,
    第一个阶段就是加载,他会将类的Class文件读入内存,并为之创建一个java.lang.Class对象,此过程由类的加载器完成;
    第二个阶段就是连接,分成了三个小的阶段,验证、准备、解析,第二个阶段连接做完之后,将类的二进制数据合并到JRE运行环境中;
    第三个阶段就是初始化,加载和连接阶段是由JVM虚拟机控制的,而初始化阶段就是由程序员控制的,比如静态代码块里写什么东西,全部由程序员控制,可以输出一条语句,或者对某个静态变量进行初始化;(注意:这是类的加载阶段,不是创建阶段)
  • 4.5.2 加载阶段
    JVM 在该阶段的主要目的是将字节码从不同的数据源(可能是class文件、也可能是jar包,甚至是网络)转化为二进制字节流加载到内存中,并生成一个代表该类的java.lang.Class对象;
  • 4.5.3 连接阶段-验证
  1. 目的是为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全;
    在这里插入图片描述
  2. 包括:文件格式验证(是否以魔数 oxcafebabe开头)、元数据验证、字节码验证和符号引用验证;
    在这里插入图片描述
  3. 可以考虑使用 -Xverify:none 参数来关闭大部分的类验证措施,缩短虚拟机类加载的时间;
  • 4.5.4 连接阶段-准备
    JVM会在该阶段对静态变量,分配内存并默认初始化(对应数据类型的默认初始值,如0
    、0L、null、false等)。这些变量所使用的内存都将在方法区中进行分配;
    在这里插入图片描述
  • 4.5.5 连接阶段-解析
    虚拟机将常量池内的符号引用替换为直接引用的过程。
  • 4.5.6 初始化
  1. 到初始化阶段,才是真正开始执行类中定义的Java程序代码,此阶段是执行<clinit>()方法的过程;
  2. <clinit>()方法是由编译器按语句在源文件中出现的顺序,依次自动收集类中的所有静态变量的赋值动作和静态代码块中的语句,并进行合并;
    在这里插入图片描述
    在这里插入图片描述
  3. 虚拟机会保证一个类的<clinit>()方法在多线程环境中被正确地加锁、同步,如果多个线程同时去初始化一个类,那么只会有一个线程去执行这个类的<clinit>方法,其它线程都需要阻塞等待,直到活动线程执行<clinit>()完毕。
    在这里插入图片描述
    在这里插入图片描述

5. 获取类结构信息

5.1 获取公有的Field、Method、Constructor

5.1 获取私有的Field、Method、Constructor

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 5.1 java.lang.reflect.Field类
  1. getModifiers: 以int形式返回修饰符 【默认修饰符是0,public是1,private是2,protected是4,static是8,final是16
默认修饰符0
public1
private2
protected4
static8
final16

public(1) + static(8) = 9

  1. getType:以Class形式返回类型
    在这里插入图片描述
  • 5.2 java.lang.reflect.Method类
  1. getModifiers: 以int形式返回修饰符 【默认修饰符是0,public是1,private是2,protected是4,static是8,final是16;
  2. getReturnType: 以Class形式获取 返回类型;
    在这里插入图片描述
  3. getParameterTypes:以Class[]类型返回参数类型数组
    在这里插入图片描述
  • 5.3 java.lang.reflect.Constructor类
  1. getModifiers: 以int形式返回修饰符 【默认修饰符是0,public是1,private是2,protected是4,static是8,final是16;
  2. getParameterTypes: 以Class[]返回参数类型数组;
    在这里插入图片描述

5.2 反射爆破构造器【创建实例】

5.2.1 获取公有构造器,利用公有构造器,创建实例

5.2.2 获取私有构造器,对私有构造器进行暴破,创建实例

在这里插入图片描述

5.3 反射爆破属性

  1. 根据属性名获取Field对象
    Field field = class对象.getDeclaredField(属性名)
  2. 爆破:field.setAccessible(true);
  3. 访问:field.set(o, 值) 或者 field.set(null, 值)静态
    System.out.println(field.get(o));
    在这里插入图片描述
class Student {//类
    public int age;
    private static String name;

    public Student() {//构造器

    }

    @Override
    public String toString() {
        return "Student{" +
                "age=" + age +
                " name=" + name +
                '}';
    }
}

5.4 反射爆破方法

在这里插入图片描述在这里插入图片描述

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

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

相关文章

RabbitMQ、Kafka、RocketMQ三种消息中间件对比总结

文章目录前言侧重点架构模型消息通讯其他对比总结参考文档前言 不论Kafka还是RabbitMQ和RocketMQ&#xff0c;作为消息中间件&#xff0c;其作用为应用解耦、异步通讯、流量削峰填谷等。 拿我之前参加的一个电商项目来说&#xff0c;订单消息通过MQ从订单系统到支付系统、库存…

【国科大模式识别】第一次作业

【题目一】设 ωmax⁡\omega_{\max }ωmax​ 为类别状态, 此时对所有的 i(i1,…,c)i(i1, \ldots, c)i(i1,…,c), 有 P(ωmax⁡∣x)≥P\left(\omega_{\max } \mid \boldsymbol{x}\right) \geqP(ωmax​∣x)≥ P(ωi∣x)P\left(\omega_i \mid \boldsymbol{x}\right)P(ωi​∣x) …

理解 mysql 之 count(*)的性能问题

一、 count(*) 为什么性能差 在Mysql中&#xff0c;count()的作用是统计表中记录的总行数。而count()的性能跟存储引擎有直接关系&#xff0c;并非所有的存储引擎&#xff0c;count(*)的性能都很差。在Mysql中使用最多的存储引擎是&#xff1a;innodb 和 myisam 。 在 myisam…

手写RPC框架-整合注册中心模块设计与实现

源码地址&#xff1a;https://github.com/lhj502819/IRpc/tree/v2 思考 如果同一个服务有10台不同的机器进行提供&#xff0c;那么客户端该从哪获取这10台目标机器的ip地址信息呢&#xff1f;随着调用方的增加&#xff0c;如何对服务调用者的数据进行监控呢&#xff1f;服务提…

十五、类加载器、反射、xml

类加载器 1类加载器【理解】 作用 负责将.class文件&#xff08;存储的物理文件&#xff09;加载在到内存中 2类加载的过程【理解】 类加载时机 创建类的实例&#xff08;对象&#xff09;调用类的类方法访问类或者接口的类变量&#xff0c;或者为该类变量赋值使用反射方式来…

【C++编程调试秘籍】| 总结归纳要点

文章目录一、编译器是捕捉缺陷的最好场合1 如何使用编译器捕捉缺陷二、在运行时遇见错误该如何处理1 该输出哪些错误信息2 执行安全检查则会减低程序效率&#xff0c;该如何处理呢3 当运行时遇到错误时&#xff0c;该如何处理四、索引越界1 动态数组2 静态数组3 多维数组5 指针…

uboot驱动和Linux内核驱动有什么区别?

一、前言 uboot启动后&#xff0c;一些外设如DDR、EMMC、网口、串口、音频、显示等等已经被初始化&#xff0c;为什么Linux内核中还需要写Linux驱动呢&#xff1f; 二、uboot驱动和Linux驱动的区别 1、直观理解 驱动&#xff0c;不仅仅是为了初始化&#xff0c;还实现了一组…

《Linux》1.权限

1.用户 首先介绍一下Linux中的用户概念。Linux下有两种用户&#xff1a;超级用户&#xff08;root&#xff09;&#xff0c;普通用户。 超级用户&#xff1a;可以再linux系统下做任何事情&#xff0c;不受限制 普通用户&#xff1a;在linux下做有限的事情。 超级用户的命令提示…

FTP回复码

FTP回复码由3个数字和对应文本组成 恢复定义为3个数字编码&#xff0c;紧跟一个空格 sp&#xff0c;然后是一行文本&#xff0c;以telnet的换行符表是结束 但是&#xff0c;某些情况下&#xff0c;文本内容太长超过一行&#xff0c;这就需要在第一行和最后一行特殊处理。处理格…

C++模拟实现栈(stack)和队列 (queue)

目录 一、栈&#xff08;stack) 的介绍 二、队列&#xff08;queue) 的介绍 三、容器适配器 二、deque的简单介绍 三、模拟实现stack 3.1 stack.h 3.2 test.cpp 四、模拟实现queue 4.1 queue.h 4.2 test.cpp 一、栈&#xff08;stack) 的介绍 1. stack是一种容器适配…

字符串、内存函数的介绍(13)

目录 1、字符串函数 1、strlen 模拟实现&#xff1a; 2、strcpy 模拟实现&#xff1a; 3、strcat 模拟实现&#xff1a; 4、strcmp 模拟实现&#xff1a; 5、strncpy 6、strncat 7、strncmp 8、strstr 模拟实现&#xff1a; 9、strtok 10、strerror 11、其他字…

回顾2022年5月IB全球统考成绩,这些学校IB成绩非常亮眼

IB大考成绩放榜&#xff0c;全球17&#xff0c;3878名学生在2022年5月的考试中获得文凭课程(DP)和职业课程(CP)的成绩。今年全球640位考生获得满分45分&#xff0c;全球平均分31.98分。以下是部分公布公布成绩的学校&#xff1a; 成都树德中学国际部&#xff1a;在2022年的全球…

电商维权控价方法论

电商经济繁荣发展&#xff0c;品牌销售渠道多样化&#xff0c;带来流量的同时&#xff0c;各种渠道问题也暴露出来&#xff0c;如&#xff0c;低价、侵权……渠道秩序面临着严峻挑战&#xff0c;品牌生命周期也受到了威胁。所以&#xff0c;越来越多的品牌选择维权控价&#xf…

2022年终总结与2023新年展望

前言 时间过得太快了&#xff0c;虽然写博客已经很多年了&#xff0c;但是年终总结一直由于种种原因没有写过&#xff0c;2022年确实是魔幻的一年&#xff0c;不知不觉自己也已经研二了&#xff0c;因为疫情的原因突然放开&#xff0c;提前放假回家&#xff0c;借此机会写一下…

Git(七) - IDEA 集成 GIT

一、配置 Git 忽略文件 &#xff08;1&#xff09;问题1:为什么要忽略他们&#xff1f; 答&#xff1a;与项目的实际功能无关&#xff0c;不参与服务器上部署运行。把它们忽略掉能够屏蔽IDE工具之 间的差异。 &#xff08;2&#xff09;问题2&#xff1a;怎么忽略&#xff1f; …

TP可能用到的函数

说明 该文章来源于同事lu2ker转载至此处&#xff0c;更多文章可参考&#xff1a;https://github.com/lu2ker/ 文章目录说明in_array()filter_var()class_exists()strpos()escapeshellarg()escapeshellcmd()preg_replace()parse_str()无字母数字下划线的webshellstr_replace()e…

GNN algorithm(4): HAN, Heterogeneous Graph Attention Network

目录 background (1) heterogeneity of graph (2) semantic-level attention (3) Node-level attention (4) HAN contributions 2. Related Work 2.1 GNN 2.2 Network Embedding 3. Preliminary background 4. Proposed Model 4.1 Node-level attention ideas: …

Unity脚本(四)

视频教程&#xff1a;https://www.bilibili.com/video/BV12s411g7gU?p149 目录 键盘输入 InputManager 键盘输入 当通过名称指定的按键被用户按住时返回true&#xff1a; bool resultInput.GetKey(KeyCode.A); 当用户按下指定名称按键时的那一帧返回true&#xff1a;…

Python学习笔记——变量和简单数据类型

编码默认情况下&#xff0c;Python 3 源码文件以 UTF-8 编码&#xff0c;所有字符串都是 unicode 字符串。 当然你也可以为源码文件指定不同的编码。标识符第一个字符必须是字母表中字母或下划线 _ 。标识符的其他的部分由字母、数字和下划线组成。标识符对大小写敏感。在 Pyth…

【深度学习】机器学习\深度学习常见相关公开数据集汇总(图像处理相关数据集、自然语言处理相关数据集、语音处理相关数据集)

一、前言 1. 介绍 常来说&#xff0c;深度学习的关键在于实践。从图像处理到语音识别&#xff0c;每一个细分领域都有着独特的细微差别和解决方法。 然而&#xff0c;你可以从哪里获得这些数据呢&#xff1f;现在大家所看到的大部分研究论文都用的是专有数据集&#xff0c;这…