【五一创作】Java 反射

news2024/10/7 11:28:37

在了解反射前,我们先要知道一些相关知识

Class类

Class类的实例表示java应用运行时的类或接口,每个java类运行时都在JVM里表现为一个class对象,可通过类名.class、类型.getClass()、Class.forName("类名")等方法获取class对象。

类的加载流程可在另一篇文章查看。

定义

Java 反射(Reflection)是指在运行时动态地获取类的信息、调用方法、获取属性等,从而实现运行时的类型检查、动态代码生成、设置和操作类的信息等功能。(动态获取的信息以及动态调用对象)。有两个特点:

1、对于任意一个类,都能够知道这个类的所有属性和方法;

2、对于任意一个对象,都能够调用它的任意一个方法和属性;

通俗的说,反射就是把java类中的各种成分映射成一个个的Java对象。

一个类有:成员变量、方法、构造方法、包等等信息,利用反射技术可以对一个类进行解剖,把个个组成部分映射成一个个对象。

需要注意的是:

反射机制的使用可能会带来一些性能上的损失,因为它需要在运行时进行类型检查和方法调用。此外,反射机制还可能会导致安全漏洞,因为它可以执行任意代码。因此,在实际开发中,需要谨慎使用反射,并且根据具体情况选择是否使用反射。

反射的实现原理

基于java虚拟机的动态加载并依赖于 Class 类,java虚拟机在运行时动态的加载类,并生成对应的class对象,这个对象包含了类的所有信息,可通过class对象获取类的信息,进而实现对类的操作。

使用时大致可分为几个步骤:

反射获取类实例 -> 反射获取方法 -> 调用method.invoke()方法

1、获取 Class 对象:通过 Class.forName() 方法获取要反射的类的 Class 对象。
2、获取 Method 对象:通过getMethod() 等方法获取要调用的方法的 Method 对象。
3、调用方法:method.invoke() 方法调用该方法(最终是由jvm执行invoke0()执行),可获取返回值。
4、获取 Field 对象:通过getField() 等方法获取要访问的属性的 Field 对象。
5、设置属性值:通过 Field.setAccessible(true) 方法将属性设置为可访问。然后可以通过 Field.get(object) 方法获取该属性的值。

下面我们一步步分析一波。

Class类对象的获取

在类加载的时候,jvm会创建一个class对象,获取class对象的方式的主要有三种:

  • 根据类名:类名.class
  • 根据对象:对象.getClass()
  • 根据全限定类名:Class.forName(全限定类名)

方法名

说明

forName()

(1)获取Class对象的一个引用,但引用的类还没有加载(该类的第一个对象没有生成)就加载了这个类。

(2)为了产生Class引用,调用forName()会立即就进行初始化。

Object-getClass()

获取Class对象的一个引用,返回表示该对象的实际类型的Class引用。

getName()

取全限定的类名(包括包名),即类的完整名字。

getSimpleName()

获取类名(不包括包名)

getCanonicalName()

获取全限定的类名(包括包名),大多数情况下和getName一样

isInterface()

判断Class对象是否是表示一个接口

getInterfaces()

返回Class对象数组,表示Class对象所引用的类所实现的所有接口。

getSupercalss()

返回Class对象,表示Class对象所引用的类所继承的直接基类。应用该方法可在运行时发现一个对象完整的继承结构。

newInstance()

返回一个Oject对象,是实现“虚拟构造器”的一种途径。使用该方法创建的类,必须带有无参的构造器。

getFields()

获得某个类的所有的公共(public)的字段,包括继承自父类的所有公共字段。 类似的还有getMethods和getConstructors。

getDeclaredFields

获得某个类的自己声明的字段,即包括public、private和proteced,默认但是不包括父类声明的任何字段。类似的还有getDeclaredMethods和getDeclaredConstructors。

首先调用了 java.lang.Class 的静态方法forName()获取反射获取类信息,调用到new instance,

newInstance() 主要做了三件事:

  1.     权限检测,如果不通过直接抛出异常;
  2.     查找无参构造器,并将其缓存起来;
  3.     调用具体方法的无参构造方法,生成实例并返回;

然后是获取构造器的过程:

  1. 先获取所有的constructors, 然后通过进行参数类型比较;
  2. 找到匹配后,通过 ReflectionFactory copy一份constructor返回;
  3. 否则抛出 NoSuchMethodException;

Constructor类及其用法

Constructor 类表示的是Class 对象所表示的类的构造方法,利用它可以在运行时动态创建对象。

方法返回值

方法名称

方法说明

static Class

forName(String className)

返回与带有给定字符串名的类或接口相关联的 Class 对象。

Constructor

getConstructor(Class... parameterTypes)

返回指定参数类型、具有public访问权限的构造函数对象

Constructor[]

getConstructors()

返回所有具有public访问权限的构造函数的Constructor对象数组

Constructor

getDeclaredConstructor(Class... parameterTypes)

返回指定参数类型、所有声明的(包括private)构造函数对象

Constructor[]

getDeclaredConstructors()

返回所有声明的(包括private)构造函数对象

T

newInstance()

调用无参构造器创建此 Class 对象所表示的类的一个新实例。

方法返回值

方法名称

方法说明

Class

getDeclaringClass()

返回 Class 对象,该对象表示声明由此 Constructor 对象表示的构造方法的类,其实就是返回真实类型(不包含参数)

Type[]

getGenericParameterTypes()

按照声明顺序返回一组 Type 对象,返回的就是 Constructor对象构造函数的形参类型。

String

getName()

以字符串形式返回此构造方法的名称。

Class[]

getParameterTypes()

按照声明顺序返回一组 Class 对象,即返回Constructor 对象所表示构造方法的形参类型

T

newInstance(Object... initargs)

使用此 Constructor对象表示的构造函数来创建新实例

String

toGenericString()

返回描述此 Constructor 的字符串,其中包括类型参数。

Field类及其用法

Field 表示Class对象所表示的类的成员变量,通过它可以在运行时动态修改成员变量的属性值(包含private)。

Field 类提供有关类或接口的单个字段的信息,以及对它的动态访问权限。

通过Class类的提供的方法来获取代表字段信息的Field对象

方法返回值

方法名称

方法说明

Field

getDeclaredField(String name)

获取指定name名称的(包含private修饰的)字段,不包括继承的字段

Field[]

getDeclaredFields()

获取Class对象所表示的类或接口的所有(包含private修饰的)字段,不包括继承的字段

Field

getField(String name)

获取指定name名称、具有public修饰的字段,包含继承字段

Field[]

getFields()

获取修饰符为public的字段,包含继承字段

方法返回值

方法名称

方法说明

void

set(Object obj, Object value)

将指定对象变量上此 Field 对象表示的字段设置为指定的新值。

Object

get(Object obj)

返回指定对象上此 Field 表示的字段的值

Class

getType()

返回一个 Class 对象,它标识了此Field 对象所表示字段的声明类型。

boolean

isEnumConstant()

如果此字段表示枚举类型的元素则返回 true;否则返回 false

String

toGenericString()

返回一个描述此 Field(包括其一般类型)的字符串

String

getName()

返回此 Field 对象表示的字段的名称

Class

getDeclaringClass()

返回表示类或接口的 Class 对象,该类或接口声明由此 Field 对象表示的字段

void

setAccessible(boolean flag)

将此对象的 accessible 标志设置为指示的布尔值,即设置其可访问性

Method类及其用法

Method 表示Class对象所表示的类的成员方法,通过它可以动态调用对象的方法(包含private)。

Method 提供关于类或接口上单独某个方法(以及如何访问该方法)的信息。

方法返回值

方法名称

方法说明

Method

getDeclaredMethod(String name, Class... parameterTypes)

返回一个指定参数的Method对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。

Method[]

getDeclaredMethods()

返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。

Method

getMethod(String name, Class... parameterTypes)

返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。

Method[]

getMethods()

返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法。

方法返回值

方法名称

方法说明

Object

invoke(Object obj, Object... args)

对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。

Class

getReturnType()

返回一个 Class 对象,该对象描述了此 Method 对象所表示的方法的正式返回类型,即方法的返回类型

Type

getGenericReturnType()

返回表示由此 Method 对象所表示方法的正式返回类型的 Type 对象,也是方法的返回类型。

Class[]

getParameterTypes()

按照声明顺序返回 Class 对象的数组,这些对象描述了此 Method 对象所表示的方法的形参类型。即返回方法的参数类型组成的数组

Type[]

getGenericParameterTypes()

按照声明顺序返回 Type 对象的数组,这些对象描述了此 Method 对象所表示的方法的形参类型的,也是返回方法的参数类型

String

getName()

以 String 形式返回此 Method 对象表示的方法名称,即返回方法的名称

boolean

isVarArgs()

判断方法是否带可变参数,如果将此方法声明为带有可变数量的参数,则返回 true;否则,返回 false。

String

toGenericString()

返回描述此 Method 的字符串,包括类型参数。

获取方法也一样,

    1. 获取所有方法列表;

    2. 根据方法名称和方法列表,选出符合要求的方法;

    3. 如果没有找到相应方法,抛出异常,否则返回对应方法;

后面调取invoke时,是通过 MethodAccessor 进行调用的,而 MethodAccessor 是个接口,在第一次时调用 acquireMethodAccessor() 进行新创建。

进行 ma.invoke(obj, args); 调用时,调用 DelegatingMethodAccessorImpl.invoke();

最后被委托到 NativeMethodAccessorImpl.invoke()

最后,再贴一张网络图

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

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

相关文章

关于 IO、存储、硬盘和文件系统

关于IO、存储、硬盘和文件系统 0.引入1.了解IO1.1.存储器IO1.2.设备IO 2.存储介质和存储类型2.1.内存2.2.硬盘2.3.固态硬盘(SSD)2.4.U盘 3.硬盘的工作原理3.1.磁头3.2.盘片3.3.电动机3.4.硬盘的读写操作 4.文件系统概述4.1.文件系统的类型4.2.文件系统的…

vagrant virtualbox 复制

菜鸟学习,记录一下 vagrant virtualbox 虚拟机复制。 目录 第一步,使用 virtualbox 复制虚拟机 第二步,复制 vagrant 文件 第三步,重命名相关文件夹及文件并修改配置: 第四步,注册运行复制后的虚拟机 第…

ImageJ实践——测量大小/长短(以细胞为例)

ImageJ是一款功能强大的图像处理软件。毫无疑问它在测量方面提供了十分便利的功能。下面我将以测量细胞的长短、大小(面积)为例,详细介绍ImageJ的测量操作流程。 1. ImageJ打开图像文件 在弹出的文件选择对话框中选择目标文件,即…

Spring Data Elasticsearch--ElasticsearchRestTemplate--使用/教程/实例

原文网址:Spring Data Elasticsearch--ElasticsearchRestTemplate--使用/教程/实例_IT利刃出鞘的博客-CSDN博客 简介 说明 本文用实例来介绍如何使用Spring Data Elasticsearch的ElasticsearchRestTemplate来操作ES。包括:索引的增删等、文档的增删改查…

【拓扑排序】课程表系列

文章目录 课程表(环检测算法)1. DFS2. BFS 课程表 II(拓扑序列)1. DFS2. BFS 课程表 IV(记忆化搜索)1. DFS2. BFS 课程表(环检测算法) 1. DFS 先修课程之间的关系可以用有向图表示&…

AI题目整理

1、网络配置时batchsize的大小怎样设置?过小和过大分别有什么特点? Batch size是指一次迭代过程中,输入到神经网络的样本数量。 batchsize太小的缺点: ①耗时长,训练效率低。 ②训练数据就会非常难收敛,从而导致欠拟合。 batch…

MySQL后台线程详解

前言 MySQL的服务实现通过后台多个线程、内存池、文件交互来实现对外服务的,不同线程实现不同的资源操作,各个线程相互协助,共同来完成数据库的服务。本章简单总结MySQL的一些后台线程以及主要作用。 本章收录在MySQL性能优化原理实战专栏&am…

js常见混淆加密技术

下面,我将通过一个案例来演示如何使用JavaScript混淆加密技术来保护你的网站。 假设你有一个网站,其中包含一个登录页面,该页面的JavaScript代码如下所示: function login(username, password) {if (username "admin"…

Doris(21):Doris的函数—日期函数

1 CONVERT_TZ(DATETIME dt, VARCHAR from_tz, VARCHAR to_tz) 转换datetime值dt,从 from_tz 由给定转到 to_tz 时区给出的时区,并返回的结果值。 如果参数无效该函数返回NULL。 select convert_tz(2019-08-01 13:21:03, Asia/Shanghai, America/Los_Angeles); select co…

大数据-玩转数据-初识FLINK

一、初识Flink Flink采用一只松鼠的彩色图案作为logo Apache Flink是一个框架和分布式处理引擎,用于对无界和有界数据流进行有状态计算。Flink被设计在所有常见的集群环境中运行,以内存执行速度和任意规模来执行计算 二、Flink的重要特点 1、事件驱动…

mysql与redis区别

一、.redis和mysql的区别总结 (1)类型上 从类型上来说,mysql是关系型数据库,redis是缓存数据库 (2)作用上 mysql用于持久化的存储数据到硬盘,功能强大,但是速度较慢 redis用于存储使…

一篇你看得懂的SNP

单核苷酸多态性,(Single Nucleotide Polymorphism,简称SNP)指的是由单个核苷酸—A,T,C或G的改变而引起的DNA序列的改变,造成包括人类在内的物种之间染色体基因组的多样性。是指在基因组上单个核苷酸的变异,…

朴素贝叶斯分类器with案例:基于SMS Spam Collection数据集的广告邮件分类

目录 贝叶斯分类器何为朴素案例:基于SMS Spam Collection数据集的广告邮件分类SMS数据集词向量表示Laplacian平滑训练过程分类过程 完整代码 贝叶斯分类器 首先要理解贝叶斯决策的理论依据,引用西瓜书上的原话:对于分类任务,在所…

(基础算法)高精度加法,高精度减法

高精度加法 什么叫做高精度加法呢?包括接下来的高精度减法,高精度乘法与除法都是同一个道理。正常来讲的话加减乘除,四则运算的数字都是整数,也就是需要在int的范围之内,但当这个操作数变得非常"大"的时候&…

《面试1v1》java反射

我是 javapub,一名 Markdown 程序员从👨‍💻,八股文种子选手。 面试官: 你好,请问你对 Java 反射有了解吗? 候选人: 是的,我了解一些。 面试官: 那你能简单…

离散数学集合论

集合论 主要内容 集合基本概念 属于、包含幂集、空集文氏图等 集合的基本运算 并、交、补、差等 集合恒等式 集合运算的算律,恒等式的证明方法 集合的基本概念 集合的定义 集合没有明确的数学定义 理解:由离散个体构成的整体称为集合&#xff0c…

【五一创作】【Midjourney】Midjourney 连续性人物创作 ② ( 获取大图和 Seed 随机种子 | 通过 seed 随机种子生成类似图像 )

文章目录 一、获取大图和 Seed 随机种子二、通过 seed 种子生成类似图像 一、获取大图和 Seed 随机种子 注意 : 一定是使用 U 按钮 , 在生成的大图的基础上 , 添加 信封 表情 , 才能获取该大图的 Seed 种子编码 ; 在上一篇博客生成图像的基础上 , 点击 U3 获取第三张图的大图 ;…

电子数据取证之宝塔面板

一、宝塔面板介绍 1、官网bt.com,是提升运维效率的服务器管理软件,支持一键WAMP/LAMP/LNMP等100多项服务器管理功能;是跨平台的软件,同时支持Windows和Linux。开源永久免费。提高工作效率,对小白比较友好。 2、怎么看服…

【网络socket编程----预备知识和UDP服务器模拟实现】

文章目录 一、预备知识1.1 理解IP地址和端口号1.2 认识TCP协议和UDP协议1.3 网络字节序1.4 socket编程接口和sockaddr结构 二、封装 UdpSocket 一、预备知识 1.1 理解IP地址和端口号 众所周知,每台主机都有一个IP地址。而主机和主机之间通信,也需要依赖…

对比学习论文阅读:CoCLR算法笔记

标题:Self-supervised Co-training for Video Representation Learning 会议:NIPS2020 论文地址:https://dl.acm.org/doi/abs/10.5555/3495724.3496201 官方代码:https://www.robots.ox.ac.uk/~vgg/research/CoCLR/ 作者单位&…