【五一创作】Java 反射

news/2024/5/19 3:31:04 标签: java, jvm, 开发语言, 反射, 面试

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

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.niftyadmin.cn/n/276213.html

相关文章

第二章 集合

系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 例如:第一章 Python 机器学习入门之pandas的使用 提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目…

基于微信小程序的考研空间站的设计与实现

基于微信小程序的考研空间站的设计与实现 摘要 随着互联网发展速度的加快,各行各业都在考虑利用互联网管理信息,微信小程序应用也凭借特有的开放性、开源性等优点被人们青睐。而目前,国内考研学生数量持续大幅增长,对考研信息平…

内网渗透(五十九)组策略首选项提权

组策略首选项提权 组策略的安全问题 组策略拥有强大的功能,在使用过程中,如果使用不当或被攻击者恶意滥用,就会存在严重的安全问题 组策略首选项提权 前面我们讲到了GPT的存储位置位于域控的%systemroot%\sysvol\domain\Policies 文件夹内,任何用户可以访问该文件夹。 …

( 字符串) 647. 回文子串 ——【Leetcode每日一题】

❓647. 回文子串 难度:中等 给你一个字符串 s ,请你统计并返回这个字符串中 回文子串 的数目。 回文字符串 是正着读和倒过来读一样的字符串。 子字符串 是字符串中的由连续字符组成的一个序列。 具有不同开始位置或结束位置的子串,即使…

19安徽比赛

案情背景: 经市民举报,近期经常受到中介的骚扰,办案单位进而对被举报的中介进行审讯,发现他们手上的信息来源都来自于某网站的后台管理员陈某。经查受骚扰的市民都有在该网站注册过信息。锁定嫌疑人后,办案人员迅速对嫌疑人进行了控制,经了解,陈某6月24日中午已经从该公…

zabbix监控远程主机

zabbix监控远程主机 在Zabbix服务器上安装Zabbix代理程序 在远程主机上安装Zabbix代理程序。安装方式取决于操作系统,可以从Zabbix官网上下载相应的安装包进行安装。 监控agent1 在agent1上安装agent yum install zabbix-agent另外在zabbix server上要关闭防火…

Java阶段二Day12

Java阶段二Day12 文章目录 Java阶段二Day12JDBC核心接口JDBC连接的基本流程实现DDL实现DML实现DQLPreparedStatement V20DBUtilUserController 连接池 JDBC JDBC Java数据库连接 Java Database Connectivity,是java官方提供的一套结构,用于连接DBMS并进…

sqlite基础

一.sqlite基础 1.下载与环境配置 从下载地址,点击我 这里下载适合你版本的压缩包 您需要下载 sqlite-tools-win32-*.zip 和 sqlite-dll-win32-*.zip 压缩文件。创建文件夹 C:\sqlite,并在此文件夹下解压上面两个压缩文件,将得到 sqlite3.d…