Java反射专题

目录

一.反射机制

1.Java Reflection

2.反射相关的主要类

3.反射的优缺点

4.反射调用优化—关闭访问检查

二.Class类

1.基本介绍

2.常用方法

3.获取Class对象的方式

4.那些类型有Class对象

三.类加载

1.介绍

2.类加载时机

3.类加载各阶段

四.获取类结构的信息

1. java.lang.Class类

2. java.lang.reflect.Field类

五.反射暴破

1.介绍

2.反射暴破构造器

3.反射暴破操作属性

4.反射暴破操作方法


一.反射机制

1.Java Reflection

反射机制允许程序在执行期借助于ReflectionAPI获取任何类的内部信息(比如成员变量,构造器,成员方法等),并能操作对象的属性及方法。反射在设计模式和框架底层都会用到。

加载完类后,在堆中就产生了一个Class类型的对象,这个对象包含了类的完整结构信息。通过这个对象得到类的结构。

下面是反射的原理图:

后面的内容也会用到这个图。

2.反射相关的主要类

说明

java.lang.Class代表一个类,Class对象表示某个类加载后在堆中的对象
java.lang.reflect.Method代表类的方法,Method对象表示某一个类的方法
java.lang.reflect.Field代表类的成员变量,Field对象表示某个类的成员变量
java.lang.reflect.Constructor代表类的构造方法,Constructor对象表示构造器

3.反射的优缺点

优点:可以动态的创建和使用对象(也是框架底层核心),使用灵活,没有反射机制,框架技术就失去底层支撑。

缺点:使用反射基本是解释执行,对执行速度有影响。

4.反射调用优化—关闭访问检查

Method、Field和Constructor对象都有setAccessible()方法。setAccessible()的作用是启动和禁用访问安全检查的开关。参数为true表示反射的对象在使用是取消访问检查,提高反射的效率。参数为false则表示反射的对象执行访问检查。

二.Class类

1.基本介绍

Class也是类,也继承于Object类。Class类不是new出来的,而是系统创建的。对于某一个类的Class对象,在内存中只有一份,因此类只加载一次。每个类的实例都会记得自己是由哪个Class实例所完成。通过Class对象可以完整地得到一个类的完整结构。类的字节码二进制数据,是放在方法区的。

2.常用方法

方法说明
forName(String name)返回指定类名 name 的 Class 对象
newInstance()调用缺省构造函数,返回给Class对象的一个实例
getName()返回此Class对象所表示的实体名称
getSuperClass()返回当前Class对象的父类的Class对象
getInterfaces()获取当前Class对象的接口
getClassLoader()返回该类的类加载器
getSuperclass()返回表示此Class所表示的实体的超类的Class
getConstructors()返回一个包含某些Constructor对象的数组
getDeclaredFields()返回Field对象的一个数组
getMethod(String name,Class ...paramType)返回一个Method对象,此对象的形参类型为paramType

应用示例:

String classAllPath="newBag.Cat";
//1.获取Cat类 对应的Class对象
Class<?> cls = Class.forName(classAllPath);
//2.输出cls
System.out.println(cls);    //显示cls对象,是哪个类的Class对象
System.out.println(cls.getClass());     //输出cls运行类型
//3.得到包名
System.out.println(cls.getPackage().getName());
//4.得到全类名
System.out.println(cls.getName());
//5.通过cls创建对象实例
Cat cat=(Cat) cls.newInstance();
System.out.println(cat);
//6.通过反射获取属性brand
Field name = cls.getField("name");
System.out.println(name.get(cat));
//7.通过反射给属性赋值 name
name.set(cat,"大橘");
System.out.println(name.get(cat));
//8.得到所有的属性(字段)
Field[] fields = cls.getFields();
for(Field f:fields){System.out.println(f.getName());
}

3.获取Class对象的方式

1)已知一个类的全类名,且该类在类路径下,可通过Class类的静态方法 forName() 获取。应用场景:多用于配置文件,读取类全路径,加载类。

补充:全类名(Fully Qualified Class Name)是一个类的完整名称,它包含了类所在的包名以及类名本身。全类名的目的是在整个Java程序或Java环境中唯一地标识一个类。

String classAllPath="newBag.Cat";
Class cls=Class.forName(classAllPath);

2)若已知具体的类,通过类的class获取,该方法最为安全可靠,程序性能最好。应用场景:多用于参数传递,比如通过反射得到对应构造器对象。

Class cls=类名.class;
Class cls= Cat.class;

3)已知某个类的实例,调用该实例的getClass()方法获取。应用场景:通过创建好的对象,获得Class对象。

Cat cat = new Cat();
Class cls = cat.getClass();

4)通过类加载器获取。

ClassLoader cl=对象.getClass().getClassLoader();
Class clazz=cl.loadClass("类的全类名");String classAllPath="newBag.Cat";
Cat cat = new Cat();
ClassLoader classLoader = cat.getClass().getClassLoader();
Class cls = classLoader.loadClass(classAllPath);

5)基本数据(int等)使用 Class cls=基本数据类型.class;

Class cls=基本数据类型.class;
Class<Integer> integerClass = int.class;

基本数据类型对应的包装类,使用 Class cls=包装类.TYPE;

Class cls=包装类.TYPE;
Class<Integer> type = Integer.TYPE;

4.那些类型有Class对象

1)外部类,成员内部类,静态内部类,局部内部类,匿名内部类;2)interface:接口;3)数组;4)enum:枚举;5)annotation:注解;6)基本数据类型;7)void。

三.类加载

1.介绍

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

加载有两种类型:

静态加载:编译时加载相关的类,如果没有则报错,依赖性太强。

例子:

public static void main(String[] args){Scanner scan=new Scanner(System.in);String str=scan.nextLine();switch (str){case "1":Dog dog=new Dog();break;case "2":System.out.println("输入了2");break;}
}

我们并没有写Dog类,搜易编译器会报错,告诉我们没有Dog类。这就是静态加载,即在编译时就加载了,没有写直接告诉我们错了。

动态加载:运行时加载需要的类,如果运行时不用该类,即使不存在也不会报错,降低了依赖性。

例子:

public static void main(String[] args) throws ClassNotFoundException {Scanner scan=new Scanner(System.in);String str=scan.nextLine();switch (str){case "1":System.out.println("输入了1");break;case "2":Class cat = Class.forName("Cat");break;}
}

我们没有写Cat类,但是编译器不会报错。接着我们运行代码,只要我们不选2,就不会报错。只有选了2,才会出现错误。这就是动态加载,不用就没事。

2.类加载时机

1)当创建对象时(new)进行静态加载;

2)当子类被加载时,父类也加载(静态加载);

3)调用类中的静态成员时进行静态加载;

4)通过反射加载类是动态加载。

3.类加载各阶段

3.1 加载

JVM在该阶段的主要目的是将字节码从不同的数据源(可能是class文件、jar包等)转化为二进制字节流加载到内存中,并生成一个代表该类的java.lang.Class对象

3.2 验证

目的是为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机本身的安全。包含:文件格式验证(是否以oxcafebabe开头)、元数据验证、字节码验证和符合引用验证

3.3 准备

JVM会在该阶段对静态变量,分配内存并默认初始化(对应数据类型的默认初始值,如0、0L、null、false等)。这些变量所使用的内存都将在方法区中进行分配

//n1是实例属性,不是静态变量,在准备阶段不会分配内存
public int n1=10;
//n2是静态变量,分配内存;n2默认初始化为0,而不是10
public static int n2=10;

3.4 解析

虚拟机将常量池内的符号引用替换为直接引用的过程

3.5 初始化

到初始化阶段,才真正开始执行类中定义的Java程序代码,此阶段是执行<clinit>()方法的过程。

什么是<clinit>()方法呢?

<clinit>()方法是由编译器按语句在源文件中出现的顺序,依次自动收集类中的所有静态变量的赋值动作和静态代码块中的语句,并进行合并。

四.获取类结构的信息

1. java.lang.Class类

方法说明
getName()获取全类名
getSimpleName()获取简单类名
getFields获取所有public修饰的属性,包含本类以及父类的
getDeclaredFields获取本类中的所有属性
getMethods获取所有public修饰的方法,包含本类以及父类的
getDeclaredMethods获取本类中所有方法
getConstructors获取所有public修饰的构造器,包含本类,没有父类
getDeclaredConstructors获取本类中所有构造器
getPackage以Package形式返回 包信息
getSuperClass以Class形式返回父类信息
getInterfaces以Class[]形式返回接口信息
getAnnotations以Annotation[]形式返回注解信息

2. java.lang.reflect.Field类

方法说明
getModifiers以int形式返回修饰符 ,返回0是默认修饰符,1是public,2是private,4是protected,8是static,16是final
getType以Class形式返回类型
getName返回属性名

五.反射暴破

1.介绍

首先我要知道这个反射暴破是干什么的?

暴破即暴力破解,我们可以通过暴破操作一些私有属性(private)的构造器、属性和方法。

2.反射暴破构造器

Class类相关方法:

newInstance:调用类中的无参构造器,获取对应类的对象

getConstructor(Class...):根据参数列表,获取对应的构造器对象

getDecalaredConstructor(Class...):根据参数列表,获取对应构造器对象

Constructor类相关方法:

setAccessible:暴破

newInstance(Object...):调用构造器

//例子
Class<?> cls = Class.forName("User");Constructor<?> constructor = cls.getDeclaredConstructor(String.class, int.class);constructor.setAccessible(true);Object o = constructor.newInstance("Tom", 13);System.out.println(o);

3.反射暴破操作属性

暴破:setAccessible(true)。

访问:set(o,值)和get(o)。

如果属性是静态的,set和get中的参数o可以写成null。

Class<?> cls = Class.forName("Person");Object o = cls.getConstructor(String.class, int.class).newInstance("Tom", 0);Field age = cls.getDeclaredField("age");age.setAccessible(true);age.set(o,14);System.out.println(o);

4.反射暴破操作方法

暴破:setAccessi(true);

访问:invoke(o,参数列表);如果是静态方法,这里的o可以换从null

Class<?> student = Class.forName("Student");Method getIm = student.getDeclaredMethod("getIm", int.class, String.class);getIm.setAccessible(true);getIm.invoke(null,13,"Tom");//下面是getIm方法
private static void getIm(int age,String s){System.out.println(age+" "+s);
}

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

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

相关文章

基于微信小程序的网上商城+ssm论文源码调试讲解

2 系统开发环境 2.1微信开发者工具 微信开发者工具现在已经被小程序开发团队开发运行&#xff0c;目前微信开发者工具任然在不断的完善中&#xff0c;在开发小程序时经常要不断的更新。可以使用微信扫码登陆开发者工具&#xff0c;开发者工具将使用这个微信帐号的信息进行小程…

教育领域中聊天机器人和会话代理的使用分析和趋势:一项文献计量学回顾

英文标题: Analysis and Trends in the Use of Chatbots and Conversational Agents in Education: a Bibliometric Review 作者信息: Dennis Arias-Chvez, Universidad Continental, Arequipa, Per; dariascontinental.edu.pe; ORCID: ORCIDTeresa Ramos-Quispe, Universida…

网络连接失败的解决方案

文章目录 问题描述解决方案 问题描述 在公司连不上网&#xff0c;域名解析没问题&#xff0c;经检测是IP地址有问题 解决方案

.NET 一款提权工具:Sharp4PetitPotato

01阅读须知 此文所提供的信息只为网络安全人员对自己所负责的网站、服务器等&#xff08;包括但不限于&#xff09;进行检测或维护参考&#xff0c;未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作。利用此文所提供的信息而造成的直接或间接后果和损失&#xf…

使用 YOLOv 11 模型实现实时手语检测 可同时识别多个手语手势

项目&#xff1a;Yolo11 - Roboflow - OpenCV 手语是聋哑人之间以及他们与外界沟通的重要工具&#xff0c;然而&#xff0c;许多不会手语的人无法与他们有效交流。这个项目的目标是通过自动检测手语手势&#xff0c;构建一个可以帮助聋哑人和普通人之间沟通的桥梁&#xff0c;…

PCL 法向量精细化处理

目录 一、概述 1.1原理 1.2实现步骤 1.3应用场景 二、代码实现 2.1关键函数 2.1.1 pcl::NormalEstimationOMP 2.1.2 pcl::NormalRefinement 2.1.3 visualizePointCloud 2.2完整代码 三、实现效果 PCL点云算法汇总及实战案例汇总的目录地址链接&#xff1a; PCL点云…

非酒精性脂肪性肝炎NASH临床赛道的百米冲刺,谁将成为胜者?

前 言 非酒精性脂肪性肝炎&#xff08;NASH&#xff09;是一种与肥胖、血脂异常、2型糖尿病和代谢综合征密切相关的疾病&#xff0c;可能会发展为肝硬化、终末期肝病甚至肝癌。据美国肝脏基金会统计数据显示&#xff0c;截至2023年8月&#xff0c;美国成年人中有5%的NASH患者…

【牛客刷题实战】BC120 争夺前五名

大家好&#xff0c;我是小卡皮巴拉 文章目录 目录 牛客题目&#xff1a; BC120 争夺前五名 题目描述 输入描述&#xff1a; 输出描述&#xff1a; 示例1 示例2 解题思路&#xff1a; 具体思路&#xff1a; 题目要点&#xff1a; 完整代码&#xff1a; 兄弟们共…

WMS 智慧仓储管理系统的可视化管理_SunWMS

【大家好&#xff0c;我是唐Sun&#xff0c;唐Sun的唐&#xff0c;唐Sun的Sun。一站式数智工厂解决方案服务商】 WMS 智慧仓储管理系统的可视化管理主要表现在以下几个方面&#xff1a; 首先是库存可视化。通过系统&#xff0c;仓库管理人员能够以直观的图表、图形等形式清晰地…

基于sklearn的机器学习应用平台 v2.0

基于sklearn的机器学习应用平台 v2.0 链接&#xff1a;https://pan.baidu.com/s/1nvHMTrtBmtPLT4oNXdw74A 提取码私信博主获取 关于作者 作者&#xff1a;小白熊 作者简介&#xff1a;精通python、matlab、c#语言&#xff0c;擅长机器学习&#xff0c;深度学习&#xff0c;机…

【实时计算 Flink】检查点和快照超时的诊断方法与调优策略

Flink的状态管理是一个复杂而关键的领域&#xff0c;涉及到作业的性能、稳定性和资源利用等多个方面。通过对状态生成机制和优化策略地深入理解与正确应用&#xff0c;结合实时计算Flink版提供的产品能力&#xff0c;可以帮您有效地优化Flink作业以应对大规模状态作业带来的挑战…

卫瓴科技,驶向「协同CRM」深水区

在卫瓴协同CRM的产品之上&#xff0c;能看到的不单纯是产品本身&#xff0c;即“提高转化率”这个单纯的指标&#xff0c;而更多的是在产品之中蕴含的“现代企业营销建设”的科学理念和认知。以此为基础&#xff0c;企业可以构建真正有价值且能长期驱动的品牌营销模型。 作者…

是德(Keysight)N9030A、N9030B PXA信号分析仪

Keysight N9030B PXA 信号分析仪是加速高要求应用创新的性能基准。 PXA 提供从优秀到卓越的测量选项&#xff0c;让您处于领先地位。利用高达 510 MHz 的分析带宽和优于 70 dB 的 SFDR 来分析最新信号&#xff0c;并通过本底噪声扩展 (NFE) 揭示以前隐藏的信号。要了解设备的真…

pdf怎么加密码怎么设置密码?这几种pdf设置密码的方法简单!

pdf怎么加密码怎么设置密码&#xff1f;PDF格式作为现代办公和学习中频繁使用的文档类型&#xff0c;其身影遍布于各类场景&#xff0c;然而&#xff0c;在享受PDF带来的便利之余&#xff0c;不少用户对其安全性产生了疑虑&#xff0c;尽管PDF文件相较于其他格式更难被直接编辑…

养生健康:从日常细节中寻觅长寿之钥

养生健康&#xff1a;从日常细节中寻觅长寿之钥 在这个快节奏的时代&#xff0c;健康似乎成了一种奢侈品&#xff0c;但实则不然。养生之道&#xff0c;不在于繁复的仪式&#xff0c;而在于融入日常的点点滴滴。今天&#xff0c;就让我们一起探讨几个简单却至关重要的养生习惯…

冷流还是热流

https://www.youtube.com/watch?vM8YtV47kaqA&t607s pl学习视频 什么是冷流&#xff1f; fun fibonacci(): Flow<BigInteger> flow {var x BigInteger.ZEROvar y BigInteger.ONEwhile (true) {println("fibonacci while $x")emit(x)x y.also {y x}…

【GESP】C++一级练习BCQM3033,略微复杂的计算,国庆七天乐

应该算第一道对小学生来说&#xff0c;计算逻辑稍微复杂一点的题目。多定义几个变量可能对解题过程更有帮助。 题解详见&#xff1a;https://www.coderli.com/gesp-1-bcqm3033/ 【GESP】C一级练习BCQM3033&#xff0c;略微复杂的计算&#xff0c;国庆七天乐 | OneCoder应该算第…

前端vue-安装pinia,它和vuex的区别

创建一个store的目录&#xff0c;任意一个js文件&#xff0c;再导入pinia&#xff0c;再定义

虚拟化数据恢复—互斥不当导致vmfs卷损坏的数据恢复案例

虚拟化数据恢复环境&#xff1a; 某企业信息管理平台&#xff0c; 几台VMware ESX Server主机共享一台存储设备&#xff0c;大约有几十台虚拟机。 虚拟化故障&原因&#xff1a; Vcenter报告虚拟磁盘丢失。管理员通过ssh远程到ESX中执行fdisk -l命令查看磁盘&#xff0c;发…

Authentication Lab | Client Side Auth

关注这个靶场的其它相关笔记&#xff1a;Authentication Lab —— 靶场笔记合集-CSDN博客 0x01&#xff1a;Client Side Auth 前情提要 有些时候&#xff0c;开发人员会将身份验证的逻辑写于前端&#xff0c;这样写是十分不安全的&#xff0c;因为前端的代码几乎全部都是可见的…