什么是JAVA反射??? 常用的API有哪些???怎么获取Class对象.....

embedded/2024/11/30 8:20:13/

目录

引言:

一、获取Class对象的方法

二、使用反射获取构造方法

三、使用反射获成员变量的方法

四、使用反射获成员方法

五.反射的优缺点有哪些?

优点包括:

缺点包括:

总结:


引言:

什么是反射:反射其实我们很早就知晓了,比如我们经常访问一个对象的方法,idea给的提示就是通过反射来获取的(dogo!!!)
反射技术作为编程语言中的一项强大工具,允许我们在运行时对类的字段方法构造函数进行编程访问。这一特性使得反射在框架设计、插件系统、单元测试等场景中有着广泛的应用。本文将详细介绍如何通过反射技术获取Class对象,进而访问类的构造方法、属性和方法。

简而言之反射就是霸道的,在反射面前,就是透明的!!!我可以随意获取到你的任何属性信息,然后去操作本且去修改它!!!

使用方法:

主要包括2个步骤:获取 解剖

首先获取class 对象,然后通过class 对象获取到我们想要的属性,比如成员变量,构造方法,成员方法。然后通过这些就可以再次细获取他们信息,比如(类型,名字,修饰符...) ,甚至你还可以去修改他们的值!!!(包括私有的属性)所有说反射就是破坏封装性的!!!

详细如下: 


一、获取Class对象的方法

在反射技术中,获取Class对象是进行后续操作的基础。以下是三种获取Class对象的方法:

自定义了一个学生类:私已成员变量和私有set方法共有get方法,后续演示:

java">package com.hz.example;public class Student {private String name;private int age;public Student() {}public Student(String name) {}private Student( int age) {this.age = age;}private Student(String name, int age) {this.name = name;this.age = age;}public int getAge() {return age;}private void setAge(int age) {this.age = age;}public String getName() {return name;}private void setName(String name) {this.name = name;}private void eat(String something){System.out.println("Student is eating "+something);}private String eat(String something1,int munch){return "Student is eating "+something1+" and he has eaten"+munch+"no of times";}public void show(){System.out.println("Student is eating");}
}
  1. 通过类名获取:  使用Class.forName(String className)方法,其中className为类的全类名(包名 +类名)(快捷键 :鼠标点击你要获取的类 然后:ctrl +alt + shift + c)  例如,Class<?> clazz = Class.forName("com.hz.example.Student"); 此方法会源代码阶段去调用java 文件 -> class文件

  2. 通过类字面量获取:使用类名.class的方式。这是最直接、最常用的获取Class对象的方法。例如,Class<?> clazz = Student.class;(加载阶段使用)

  3. 通过对象获取:使用对象.getClass()方法。如果已有一个类的实例对象,可以通过该方法获取其Class对象。例如,Student student = new Student();; Class<?> clazz = Student.getClass(); (运行阶段使用)

使用场景总结:

  • Class.forName:适用于需要根据字符串形式的类名动态加载类的情况,常用于框架设计、插件机制等。
  • 对象.getClass:适用于已有一个类的实例对象,需要获取该对象的 Class 对象以进行反射操作的情况。
  • 类名.class:适用于编译时就已知要操作的类,是最简单、最常用的获取 Class 对象的方法。

二、使用反射获取构造方法

获取了Class对象后,我们就可以通过反射来获取类的构造方法。构造方法分为私有和公有两种,通过反射我们可以访问这两种构造方法。

小知识:java中,万物接可对象,java中也定义了相应的类来描述构造方法,成员方法,成员变量:

  1. 构造方法:  Constructor
  2. 成员方法;     Method
  3. 成员变量:   Field

 通过这些就可以很快获取到相应对象,进而去操作他们!!!

  1. 获取所有构造方法

    1. 使用Class.getConstructors()方法获取所有公有的构造方法;构造方法就是通过Constructor获取,然后加s 就是获取所有公共的构造方法,返回的就是数组,

    2. 使用Class.getDeclaredConstructors()方法获取所有(包括私有)构造方法。Declared就是权限的意思,那么类似root 你可以获取所有的,包括私有的,然后下面获取成员变量,方法也一样了!!

  2. 获取特定构造方法

    1. 使用Class.getConstructor(Class<?>... parameterTypes)方法根据参数类型获取公有的构造方法,(没加s,就表示获取单个的,本且没有加Declared,就自然获取指定公共的)      

    2. 使用Class.getDeclaredConstructor(Class<?>... parameterTypes)方法根据参数类型获取所有(包括私有)构造方法。

  3. 创建对象:获取了构造方法后,可以

    1. 使用Constructor.newInstance(Object... initargs)方法来创建对象实例

    2. 当然,有时候私已的private还得用 setAccessible(boolen flag) 去更改它的权限为true 才可以去操作:

简单Demo: 

java">// 通过类名获取Class对象Class<?> aClass = Class.forName("com.hz.example.Student");// 获取类的所有公共构造方法Constructor<?>[] constructors = aClass.getConstructors();// 获取类的所有构造方法,包括私有、受保护和默认访问级别的构造方法Constructor<?>[] declaredConstructors = aClass.getDeclaredConstructors();// 获取接受一个String类型参数的公共构造方法Constructor<?> constructor = aClass.getConstructor(String.class);// 获取接受一个String类型和一个int类型参数的私有构造方法Constructor<?> declaredConstructor = aClass.getDeclaredConstructor(String.class, int.class);// 设置该构造方法为可访问declaredConstructor.setAccessible(true);// 使用该构造方法创建Student对象Student student = (Student) declaredConstructor.newInstance("张三", 18);

原Demo: 

三、使用反射获成员变量的方法

其实下面也差不多了!! 

Class类中用于获取成员变量的方法


Field[] getsields():        返回所有公共成员变量对象的数组
Field[]getDeclaredFields():        返回所有成员变量对象的数组
Field getField(String name):        返回单个公共成员变量对象
Field getDeclaredField(String name):        返回单个成员变量对象


Field类中用于创建对象的方法
void set(Object obj, Object value):        赋值
Object get(Object obj)         获取值。

参考Demo: 

java">// 获取Student类的Class对象
Class<?> aClass = Class.forName("com.hz.example.Student");// 获取Student类的所有公共字段(包括继承自父类的字段)
Field[] fields = aClass.getFields();
for (Field field : fields) {// 打印每个公共字段的信息System.out.println(field);
}// 获取Student类声明的所有字段,包括私有字段,但不包括继承的字段
Field[] declaredFields = aClass.getDeclaredFields();// 通过字段名获取Student类的公共字段对象"name"
Field name = aClass.getField("name");
System.out.println(name);// 获取字段名
String name1 = name.getName();// 获取字段类型
Class<?> type = name.getType();
System.out.println(name1 + "  " + type);// 创建Student类的实例对象
Student student = new Student("hz");// 设置字段可访问性,以便可以访问私有字段
name.setAccessible(true);// 通过反射获取student对象"name"属性的值
Student value = (Student) name.get(student);
System.out.println("通过反射获取 创建对象name属性的值value = " + value);// 通过反射修改student对象"name"属性的值为"mn"
name.set(student, "mn");// 打印修改后的"name"属性值
System.out.println("修改后的name的值为:" + student.getName());

四、使用反射获成员方法

Class类中用于获取成员方法的方法:


Method[]getMethods():返回所有公共成员方法对象的数组,包括继承的
Methodl] getDeclaredMethods():返回所有成员方法对象的数组,不包括继承的
Method getMethod(String name, Class<?>... parameterTypes):返回单个公共成员方法对象
Method getDeclaredMethod(String name, Class<?>.. parameterTypes):返回单个成员方法对象


Method类中用于创建对象的方法;


Object invoke(Object obj, Object... args):运行方法
参数一:用obj对象调用该方法
参数二:调用方法的传递的参数(如果没有就不写)
返回值:方法的返回值(如果没有就不写)

getMethodsgetDeclaredMethods 区别,getMethods获取公共以外,还会获取父类的方法:我这里没有,但是有一个祖宗 Object !!!!

getMethod getDeclaredMethod获取 指定方法的时候: 除了指定方法的名字外,还得去指定他们的参数类型,主要是区分方法重载!!!!(其实和什么类似,构造方法因为名字都一样,不用指定,但是也指定了参数的类型,这些都是类似的!!!)

invoke() 运行方法:

java">// 获取Student类的Class对象
Class<?> aClass = Class.forName("com.hz.example.Student");// 通过反射获取Student类中名为"eat"的方法,该方法接收一个String类型的参数
Method eat = aClass.getDeclaredMethod("eat", String.class);// 设置该方法为可访问,即使它是私有的也可以被访问
eat.setAccessible(true);// 创建Student类的实例
Student student = new Student();// 调用Student对象的eat方法,并传入"苹果"作为参数
// 注意:由于eat方法没有返回值,因此这里不需要处理返回值
// 原eat 方法没有返回值 就不用管
eat.invoke(student,"苹果");// 通过反射获取Student类中名为"eat"的另一个方法,该方法接收一个String类型和一个int类型的参数
Method eat1 = aClass.getDeclaredMethod("eat", String.class, int.class);// 同样设置该方法为可访问
eat1.setAccessible(true);// 调用Student对象的eat方法,并传入"蔡徐坤"和999作为参数
// 由于该方法有返回值,且我们期望返回值为String类型,因此进行类型转换
String invoke = (String) eat1.invoke(student, "蔡徐坤", 999);// 打印返回值
System.out.println(invoke);

五. 反射的优缺点有哪些?


优点包括:

  1. 动态性:反射允许在运行时动态地获取和操作类的信息,而不需要在编译时知道类的具体细节。
  2. 灵活性:反射可以通过类名字符串来创建对象实例,可以在运行时动态地调用方法和字段,以及访问和修改私有成员。
  3. 扩展性:反射可以用于实现一些高级功能,如动态代理、注解处理和依赖注入等。


缺点包括:

  1. 性能损耗:由于反射需要在运行时获取和操作类的信息,所以相比直接调用,反射操作通常会导致性能下降。
  2. 安全问题:反射可以访问和修改私有成员,这可能破坏了封装性和安全性,因此,在使用反射时需要谨慎处理权限和访问控制。
  3. 编码复杂性:反射的使用和理解相对复杂,容易引入错误和难以调试。同时,反射操作也不受编译器的类型检查,可能导致运行时异常。

六. 总结:


反射技术为我们在运行时动态地访问和修改类的字段、方法和构造函数提供了强大的能力。在实际应用中,反射技术有着广泛的应用场景,如框架设计、插件系统、单元测试等。然而,反射技术也带来了一定的性能开销和安全性问题,因此在使用时需要权衡其利弊。


http://www.ppmy.cn/embedded/141692.html

相关文章

Linux开发者的CI/CD(11)jenkins变量

文章目录 1. **环境变量 (Environment Variables)**常见的环境变量:示例:2. **构建参数 (Build Parameters)**常见的构建参数类型:示例:3 **在 `stages` 块内定义局部变量**示例:使用 `script` 步骤定义局部变量4 变量引用陷阱在 Jenkins 中,变量是自动化流程中非常重要的…

Vue进阶面试题目(四)

1. 什么是双向绑定? Vue 双向绑定的原理是什么? 双向绑定是一种数据绑定机制&#xff0c;指的是视图和数据之间可以相互同步。即&#xff0c;当模型数据&#xff08;Model&#xff09;发生变化时&#xff0c;视图&#xff08;View&#xff09;会自动更新&#xff1b;反之&am…

使用PyQt5开发一个GUI程序的实例演示

一、安装Python 下载安装到这个目录 G:\Python38-32 安装完成有这些工具&#xff0c;后面备用&#xff1a; G:\Python38-32\Scripts\pyrcc5.exe G:\Python38-32\Scripts\pyuic5.exe 二、PyQt环境配置 pip install PyQt5 pip install pyqt5-tools 建议使用国内源&#xff0c…

随机变量的线性最小均方估计(LMMSE)——多个观测变量

假设有一个随机变量 x x x需要估计&#xff0c;目标是找到一个线性估计器 x ^ ∑ i 0 N − 1 a i y i b \hat{x} \sum_{i0}^{N-1} a_i y_i b x^∑i0N−1​ai​yi​b&#xff0c;使得估计误差 e x − x ^ e x - \hat{x} ex−x^的均方误差 E [ e 2 ] E[e^2] E[e2]最小。 …

记一次 .NET某hdp智能柜系统 卡死分析

一&#xff1a;背景 1. 讲故事 停了一个月时间没有更新博客了&#xff0c;主要是这段时间有些许事情导致心神不宁&#xff0c;我这个人也比较浮躁所以无法潜心修炼&#xff0c;事情如下&#xff1a; 被狗咬了 也不知道是不是出门没看黄历&#xff0c;在小区门口店里买烟&am…

uniapp实现轮播图结构数据渲染

实现轮播图结构数据渲染 swiper swiper | uni-app官网 (dcloud.net.cn) 滑块视图容器。【设计人员应以375px的宽度设计小程序】 一般用于左右滑动或上下滑动&#xff0c;比如banner轮播图。 组件代码 <swiper indicator-dots circular><swiper-item v-for"i…

HTML 画布:网页上的创意绘图板

HTML 画布:网页上的创意绘图板 HTML5的画布(Canvas)元素为网页开发者提供了一种在网页上绘制图形和动画的强大工具。它是HTML5标准的一部分,被设计为允许脚本语言(通常是JavaScript)动态渲染图形、图像和动画。在这篇文章中,我们将深入探讨HTML画布的各个方面,包括其基…