Java反射机制详解:动态访问和操作对象

目录

  1. 先看个例子
  2. 基本概念
  3. Class 2.1 获取Class 2.2 通过Class获取类修饰符和类型
  4. Member 3.1 Field 3.1.1 获取Field 3.1.2 获取变量类型、修饰符、注解 3.1.3 获取、设置变量值 3.2 Method 3.2.1 获取Method 3.2.2 获取方法返回类型 3.2.3 获取方法参数类型 3.2.4 获取方法声明抛出的异常类型 3.2.5 获取方法参数名称 3.2.6 通过反射调用方法 3.3 Constructor 3.3.1 获取构造方法 3.3.2 创建对象
  5. 数组和枚举 4.1 数组 4.2 枚举
  6. 反射的缺点 参考

1. 先看个例子

public class People {private People(int age) {}public void show() {System.out.println("test reflect");}
}//test code
Class<?> clazz = Class.forName("com.xfhy.ref.People");
Constructor<?> declaredConstructor = clazz.getDeclaredConstructor(int.class);
declaredConstructor.setAccessible(true);
People person = (People) declaredConstructor.newInstance(12);
person.show();
通过这个简单的例子,我们可以看到Java反射的强大之处:即使People的构造方法是私有的,我们仍然可以通过反射机制来创建其实例。

2. 基本概念

Java的反射机制能够:

  • 对于任意一个类,都能够知道这个类的所有属性和方法。
  • 对于任意一个对象,都能够调用它的任意一个方法和属性。

这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制。反射机制主要涉及两个类:ClassMember

3. Class

Class是反射能够实现的基础,Class是JDK提供的一个类,完整路径是java.lang.Class。本质上这个类和MathString或者自己定义的各种类没有区别。

3.1 获取Class

获取Class对象的几种方法:

  • Object.getClass():对象实例调用getClass方法。
  • The.class:类调用.class,例如String.class
  • Class.forName(""):传入类的全路径。
  • The.TYPE:例如Double.TYPE
  • Class.getSuperclass():某个实例调用getClass().getSuperclass()

3.2 通过Class获取类修饰符和类型

HashMap为例,我们可以通过反射获取类的修饰符、泛型信息、实现的接口、父类和注解等信息。

Class<?> clazz = HashMap.class;
System.out.println("Class : " + clazz.getCanonicalName());
System.out.println(Modifier.toString(clazz.getModifiers()));
TypeVariable<? extends Class<?>>[] typeParameters = clazz.getTypeParameters();
StringBuilder stringBuilder = new StringBuilder("Parameters : ");
for (TypeVariable<? extends Class<?>> typeParameter : typeParameters) {stringBuilder.append(typeParameter.getName()).append(" ");
}
System.out.println(stringBuilder.toString());Type[] genericInterfaces = clazz.getGenericInterfaces();
StringBuilder interfaces = new StringBuilder("Implemented Interfaces : ");
for (Type intf : genericInterfaces) {interfaces.append(intf.toString()).append(" ");
}
System.out.println(interfaces.toString());Class<?> superclass = clazz.getSuperclass();
if (superclass != null) {System.out.println(superclass.getCanonicalName());
}Annotation[] annotations = clazz.getAnnotations();
StringBuilder annotation = new StringBuilder("Annotations : ");
for (Annotation a : annotations) {annotation.append(a.toString()).append(" ");
}
System.out.println(annotation.toString());

4. Member

Member有三个实现类:

  • java.lang.reflect.Field:类变量
  • java.lang.reflect.Method:类方法
  • java.lang.reflect.Constructor:类构造方法

4.1 Field

通过Field可以访问给定类对象的类变量,包括获取变量的类型、修饰符、注解、变量名、变量值等,即使是private的也是OK的。

4.1.1 获取Field

Class提供了四种方法获得给定类的Field

  • getDeclaredField(String name):获取指定的变量,包括private的。
  • getField(String name):获取指定的变量,只能是public的。
  • getDeclaredFields():获取所有变量,包括private的。
  • getFields():获取所有变量,只能是public的。
4.1.2 获取变量类型、修饰符、注解
Class clazz = People.class;
Field[] declaredFields = clazz.getDeclaredFields();
for (Field field : declaredFields) {StringBuilder stringBuilder = new StringBuilder();stringBuilder.append("变量名: ").append(field.getName()).append("\n");stringBuilder.append("变量类型: ").append(field.getType()).append("\n");stringBuilder.append("变量修饰符: ").append(Modifier.toString(field.getModifiers())).append("\n");Annotation[] annotations = field.getAnnotations();if (annotations.length != 0) {stringBuilder.append(" 变量注解 : ");for (Annotation a : annotations) {stringBuilder.append(a.toString()).append(" ");}}System.out.println(stringBuilder.toString());
}
4.1.3 获取、设置变量值
People people = new People("张三", 17);
Class<? extends People> peopleClass = people.getClass();
try {Field nameField = peopleClass.getDeclaredField("name");nameField.setAccessible(true);Field ageField = peopleClass.getField("age");String name = (String) nameField.get(people);int age = ageField.getInt(people);System.out.println("name = " + name + ", age = " + age);nameField.set(people, "李四");ageField.set(people, 18);System.out.println(people.toString());
} catch (NoSuchFieldException | IllegalAccessException e) {e.printStackTrace();
}

4.2 Method

4.2.1 获取Method

Class提供了四种方法获取Method

  • getDeclaredMethod(String name, Class<?>... parameterTypes)
  • getMethod(String name, Class<?>... parameterTypes)
  • getDeclaredMethods()
  • getMethods()
4.2.2 获取方法返回类型
  • getReturnType():获取目标方法返回类型对应的Class对象。
  • getGenericReturnType():获取目标方法返回类型对应的Type对象。
4.2.3 获取方法参数类型
  • getParameterTypes():获取目标方法各参数类型对应的Class对象。
  • getGenericParameterTypes():获取目标方法各参数类型对应的Type对象。
4.2.4 获取方法声明抛出的异常类型
  • getExceptionTypes():获取目标方法抛出的异常类型对应的Class对象。
  • getGenericExceptionTypes():获取目标方法抛出的异常类型对应的Type对象。
4.2.5 获取方法参数名称

.class文件中默认不存储方法参数名称,如果想要获取方法参数名称,需要在编译的时候加上-parameters参数。

4.2.6 通过反射调用方法

通过Methodinvoke()方法来反射调用目标方法,第一个参数为需要调用的目标类对象。如果方法是static的,则该参数为null,后面的参数是目标方法的参数值,顺序与目标方法声明中的参数顺序一致。

4.3 Constructor

4.3.1 获取构造方法

Method类似。

4.3.2 创建对象

一般使用java.lang.reflect.Constructor.newInstance()来构建对象,另一种Class.newInstance()已经废弃。

5. 数组和枚举

5.1 数组

数组类型:数组本质上是一个对象,所以它也有自己的类型。例如对于int[] intArray,数组类型为class [I。数组类中的[个数代表数组的维度,例如[代表一维数组,[[代表二维数组,[后面的字母代表数组元素类型,I代表int,一般为类型的首字母大写(long类型例外,为J)。

创建和初始化数组:

Object array = Array.newInstance(int.class, 2);
Array.set(array, 0, 1);
Array.set(array, 1, 2);
System.out.println(Array.get(array, 1));

多维数组:Java反射没有提供能够直接访问多维数组元素的API,但你可以把多维数组当成数组的数组处理。

5.2 枚举

枚举隐式继承自java.lang.EnumEnum继承自Object

结论

Java反射机制是Java语言的一个重要特性,它提供了一种动态访问和操作对象的能力。虽然它有性能和安全上的考量,但在需要动态性和灵活性的场景下,反射是一个不可或缺的工具。理解和掌握反射机制,可以帮助我们编写出更加灵活和强大的Java程序。

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

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

相关文章

ai外呼机器人的作用有哪些?

ai外呼机器人具有极高的工作效率。日拨打成千上万通不是问题&#xff0c;同时&#xff0c;机器人还可以快速筛选潜在客户&#xff0c;将更多精力集中在有价值的客户身上&#xff0c;进一步提升营销效果。183-3601-7550 ai外呼机器人的作用&#xff1a; 1、搭建系统&#xff0c…

福禄克DTX,DSX系列内置标准以及生成的测试报告如何解读?

今日,接到一些朋友的询问?虽然使用了很长一段时间的FLUKE DSX-5000或者DSX-8000,但是对于测试标准和测试生成的报告一知半解,借此咱们一块屡屡清楚。 1,经常有的朋友拿到设备后,第一时间就问,咱们福禄克内置的标准的多少?我线的参数(被测的铜缆)达到多少db,才能算过…

我与Linux的爱恋:磁盘的存储管理

​ ​ &#x1f525;个人主页&#xff1a;guoguoqiang. &#x1f525;专栏&#xff1a;Linux的学习 文章目录 磁盘的存储管理 磁盘的存储管理 在我们日常生活中&#xff0c;我们要打开很多文件(要打开这个文件需要先找到这个文件->要在磁盘中先找到->通过文件路径文件…

git原理与上传

言&#xff1a; git是一个软件&#xff0c;gitee/github是一个网站&#xff0c;这里有什么联系吗&#xff1f;我们身为一个程序员不可能不知道github&#xff0c;但是毕竟这是外国的网站&#xff0c;我们不翻墙的情况下&#xff0c;是无法访问的(或者就是太慢了&#xff0c;或…

Python基础学习_01

目录 1、注释 2、数字和数学计算 3、变量 4、字符串 5、打印 6、本节总结 1、注释 • 什么是注释&#xff1f; 1&#xff09;注释就是用自然语言向代码阅读者说明代码的功能和意义 • 注释 1&#xff09;单行注释使用 # 为开头&#xff1b;并且不能换行…

操作系统学习笔记-3.2虚拟内存

文章目录 虚拟内存请求分页管理方式页面置换算法最佳置换算法工作原理OPT 算法的示例最佳置换算法的优点和缺点 先进先出置换算法最近最久未使用时钟置换算法时钟置换算法的工作原理&#xff1a;算法的步骤&#xff1a; 改进型时钟置换算法改进型时钟置换算法的特点&#xff1a…

vue3 封装aixos

1. Vue3 封装 aixos 并且 使用 aixos 请求数据 npm install axios # 或者 yarn add axios 2. Vue3 封装 aixos 并且 使用 aixos 请求数据 封装 axios可以帮助我们更好地管理 HTTP 请求&#xff0c;例如添加统一的基础URL、请求头、拦截器等功能。 下面是封装 axios的一个示…

量子计算机能解决哪些问题?

经典与量子难度对比 在深入示例之前&#xff0c;我们首先讨论一下如何研究和分类各种问题的难度。有些问题可以在经典计算机上轻松解决&#xff0c;我们不需要量子计算机来解决它们。另一方面&#xff0c;有些问题非常困难&#xff0c;需要量子计算机来解决。一个著名的例子是寻…

中电金信:院长寄语|关于源启AI+行动的思考

中国电子首席科学家 中电金信研究院院长 况文川 自2022年8月19日发布以来&#xff0c;源启已经走上了她第三年的征途。今天&#xff0c;源启已经成为公司战略的支点&#xff0c;中电金信正致力于用“源启底座”“源启咨询”“源启应用重构”三位一体的方式来赋能千行百业数智化…

海康私有化视频平台EasyCVR视频分析设备平台流媒体协议RTMP、HTTP-FLV、HLS的简单对比

在当今的数字化世界中&#xff0c;视频流协议的选择对于确保流畅、高效的视频传输至关重要。随着互联网技术的快速发展&#xff0c;直播和视频点播服务已经成为人们日常生活中不可或缺的一部分。无论是安防监控、在线教育、远程会议还是娱乐直播&#xff0c;用户对于视频流的实…

详解使用python读写csv,以及将csv数据写入数据库

csv文件 csv介绍 CSV&#xff0c;也即Comma-Separated Values&#xff0c;是一种用于存储表格数据的纯文本文件格式&#xff0c;其中每一行代表一条记录&#xff0c;记录中的各个字段由逗号分隔。 姓名,年龄,性别 张三,25,男 李四,28,男 王五,22,男 六六,29,女 子柒,28,女 对…

OpenMVS OpenMVG 笔记

OpenMVS & OpenMVG 笔记 OpenMVS 和 OpenMVG 都是计算机视觉中用于三维重建的开源库。两者都可以实现从图像集合中计算出相机位姿和三维点云&#xff0c;但它们的重点略有不同。 OpenMVG 主要关注于从输入图像集合中提取稠密的特征匹配&#xff0c;通过这些匹配计算相机的…

Golang--文件操作

1、文件 文件&#xff1a;文件用于保存数据&#xff0c;是数据源的一种 os包下的File结构体封装了对文件的操作&#xff08;记得包os包&#xff09; 2、File结构体--打开文件和关闭文件 2.1 打开文件 打开文件&#xff0c;用于读取&#xff08;函数&#xff09;&#xff1a; 传…

dcdc3节锂电池串联9-12V升压32V 3A/5A 音响供电恒压芯片 SL4010

SL4010&#xff1a;高效能9-12V至32V升压解决方案&#xff0c;为高端音响系统注入澎湃动力 在追求极致音质与持久续航的音频世界里&#xff0c;SL4010 DC-DC升压转换器以其卓越的性能和可靠性&#xff0c;成为高端音响系统的理想供电伙伴。专为3节锂电池串联&#xff08;9-12V…

onnx-web + yolov8n 在视频流里做推理

顺着我上一篇文章 使用onnxruntime-web 运行yolov8-nano推理 继续说&#xff0c;有朋友在问能不能接入 视频流动&#xff0c;实时去识别物品。 首先使用 getUserMedia 获取摄像头视频流 getUserMedia API 可以访问设备的摄像头和麦克风。你可以使用这个 API 获取视频流&#…

力扣题库——136.只出现一次的数字

代码实现&#xff1a; class Solution { public:int singleNumber(vector<int>& nums) {int result0;for(int num:nums){result^num;}return result;} }; 结果&#xff1a; 思路&#xff1a;这里让0和数组元素不断异或&#xff0c;因为0与一个数异或的结果是它本身…

EasyPOI使用详解

EasyPOI 简介 easypoi功能如同名字easy,主打的功能就是容易,让一个没见接触过poi的人员 就可以方便的写出Excel导出,Excel模板导出,Excel导入,Word模板导出,通过简单的注解和模板 语言(熟悉的表达式语法),完成以前复杂的写法 文档&#xff1a;http://easypoi.mydoc.io/#categor…

JAVA设计模式之【建造者模式】

1 定义 建造者模式&#xff08;Builder Pattern&#xff09;使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式&#xff0c;它提供了一种创建对象的最佳方式。 2 类图 产品类&#xff08;Product&#xff09;&#xff1a;表示被创建的复杂…

智能化健身房管理:Spring Boot与Vue的创新解决方案

作者介绍&#xff1a;✌️大厂全栈码农|毕设实战开发&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。 &#x1f345;获取源码联系方式请查看文末&#x1f345; 推荐订阅精彩专栏 &#x1f447;&#x1f3fb; 避免错过下次更新 Springboot项目精选实战案例 更多项目…

如何修改WordPress经典编辑器的默认高度?

boke112百科有一个使用WordPress搭建的小网站&#xff0c;文章内容就是几个字不到一行&#xff0c;但是每次使用经典编辑器编辑文章时&#xff0c;都觉得编辑器默认高度太高了&#xff0c;影响了我添加文章摘要和其他属性&#xff0c;有没有办法修改WordPress经典编辑器的默认高…