前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Java基础】Java反射机制

【Java基础】Java反射机制

作者头像
全栈开发日记
发布2022-05-12 20:00:00
1580
发布2022-05-12 20:00:00
举报
文章被收录于专栏:全栈开发日记

本篇目录

1- 反射是什么? 2- 获取类对象的三种方式 3- 通过类对象获取该类的所有方法并调用 4- 通过类对象调用指定私有方法 5- 通过类对象获取所有属性并输出 6- 通过类对象获取指定属性并修改属性的值 7- 通过类对象获取指定构造方法并调用

1 反射是什么?

反射机制是Java中的一个高级特性,通过反射机制,我们可以操作任意一个类,包括获取这个类的所有属性和方法,包括私有属性和构造方法。

在我们日常开发中其实也经常接触到反射,比如我们经常使用的IDEA,当我们调用一个方法时,会动态的获取该方法的参数以及参数名称,各位就不好奇这是怎么做到的吗?

再比如Java中封神的框架Spring系列,也是大规模的使用了反射机制,最经典的就是使用Xml的方式配置Bean时需要设置全限定类名才能成功的注入Bean,为什么呢?

本篇内容我在JDK11的运行环境下以几个反射使用例子带大家学习一下反射的使用方式。

2 获取类对象的三种方式

这里的类对象和实例对象不是一个概念。确切的说,类对象是Class类的实例对象,在 java.lang 包下有一个类名为Class.java的Java文件,而我们现在要获取的类对象其实就是获取Class实例对象。下面是三种获取一个类的Class对象的方式:

第一种:通过类的实例对象获取Class对象

代码语言:javascript
复制
// 实例化Test对象
Test test=new Test();
// 获取Class对象
Class c=test.getClass();

第二种:通过类名直接获取Class对象

代码语言:javascript
复制
// 获取Class对象
Class c=Test.class;

第三种:通过类的全限定类名获取Class对象

代码语言:javascript
复制
// 利用Class类的静态方法获取指定全限定类名的Class对象
Class c=Class.forName("demo.Test");

如上就是获取类的Class对象三种方式,第三种可能大家在学习JDBC时都有接触,其实就是通过全限定类名去获取指定类的Class对象。

多代码预警,每一行代码都有注释,以帮助理解

3 通过类对象获取该类的所有方法并调用

上一段我们已经获取到了该类的类对象了,接下来就是对于类对象的作用了。

这里我们假设Test类有两个public方法和一个private方法,我们利用类对象获取到这些方法,并且调用它。

代码语言:javascript
复制
// 获取该类的Class对象
Test test = new Test();
Class<? extends Test> clazz = test.getClass();
// 获取该类的所有方法包括私有方法
Method[] methods = clazz.getDeclaredMethods();
// 遍历打印方法名
for (Method method : methods) {
    // 设置私有方法访问权限为可访问
    method.setAccessible(true);
    // 调用这个方法
    method.invoke(test, null);
}

这里比较关键的两个方法,分别是setAccessible方法和invoke方法。

setAccessible方法:可以设置私有方法或属性的访问权限为可访问,让我们可以修改和调用,没有这一步,我们就只能调用公共方法。

invoke方法:参数obj为当前类的实例对象(不是类对象),第二个参数为方法的参数列表。该方法可以实现执行目标方法。

4 通过类对象调用指定私有方法

代码语言:javascript
复制
// 创建该类的实例对象
Test test = new Test();
// 获取该类的Class对象
Class<? extends Test> clazz = test.getClass();
// 获取指定方法
Method test3 = clazz.getDeclaredMethod("test3", null);
// 设置该方法的权限为可访问
test3.setAccessible(true);
// 调用该方法
test3.invoke(test, null);

5 通过类对象获取所有属性并输出

代码语言:javascript
复制
// 创建该类的实例对象
Test test = new Test();
// 获取该类的Class对象
Class<? extends Test> clazz = test.getClass();
// 获取该类的所有属性,包括私有属性
Field[] declaredFields = clazz.getDeclaredFields();
// 遍历属性
for (Field field : declaredFields) {
    // 设置属性的访问权限为可访问
    field.setAccessible(true);
    // 打印该属性当前的值
    System.out.println(field.get(test));
}

6 通过类对象获取指定属性并修改属性的值

代码语言:javascript
复制
// 创建该类的实例对象
Test test = new Test();
// 获取该类的Class对象
Class<? extends Test> clazz = test.getClass();
// 获取指定名称的属性
Field test1 = clazz.getDeclaredField("test1");
// 设置该属性的访问权限为允许访问
test1.setAccessible(true);
// 修改该属性的值
test1.set(test, "修改后的值");
// 打印该属性的值
System.out.println(test1.get(test));

7 通过类对象获取指定构造方法并调用

代码语言:javascript
复制
// 获取类对象
Class<Test> clazz = Test.class;
// 获取指定构造方法
Constructor<Test> constructor = clazz.getConstructor(null);
// 使用该构造方法实例化对象
Test test = constructor.newInstance();
// 使用实例对象调用方法
test.test4();
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-12-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 全栈开发日记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 2 获取类对象的三种方式
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档