Java重点基础:反射机制
一、什么是反射?
Java反射说的是在运行状态中,对于任何一个类,我们都能够知道这个类有哪些方法和属性。对于任何一个对象,我们都能够对它的方法和属性进行调用。我们把这种动态获取对象信息和调用对象方法的功能称之为反射机制。
二、反射的三种方式
这里需要跟大家说一下,所谓反射其实是获取类的字节码文件,也就是.class文件,那么我们就可以通过Class这个对象进行获取。
1、第一种方式
这个方法其实是Object的一个方法,Class继承了Object,所以我们可以直接使用。
public class Test02 {
public static void main(String\[\] args) { // 创建一个对象 Test02 t = new Test02(); // 获取该对象的Class对象 Class c = t.getClass(); // 获取类名称 System.out.println(c.getName()); // com.ms.Test02 }
}
2、第二种方式
public class Test02 {
public static void main(String\[\] args) { Class c = Test02.class; // 获取类名称 System.out.println(c.getName()); // com.ms.Test02 }
}
3、第三种
这里需要注意,通过类的全路径名获取Class对象会抛出一个异常,如果根据类路径找不到这个类那么就会抛出这个异常。
public class Test02 {
public static void main(String\[\] args) { try { // 根据类的全路径名获取 Class c = Class.forName("com.ms.Test02"); // 获取类名称 System.out.println(c.getName()); // com.ms.Test02 } catch (ClassNotFoundException e) { e.printStackTrace(); } }
}
那么这3中方式我们一般选用哪种方式呢?第一种已经创建了对象,那么这个时候就不需要去进行反射了,显得有点多此一举。第二种需要导入类的包,依赖性太强。所以我们一般选中第三种方式。
三、通过反射获取类的构造方法、方法以及属性
1、获取构造方法
public class Test01 {
public static void main(String\[\] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException { // 加载Class对象 Class c = Class.forName("com.reflect.User"); System.out.println("===========================获取所有公用的构造方法=============================="); // 获取所有公用的构造方法 Constructor\[\] constructors = c.getConstructors(); for (Constructor constructor : constructors) { System.out.println(constructor); } System.out.println("=============================获取所有的构造方法============================"); // 获取所有的构造方法 Constructor\[\] declaredConstructors = c.getDeclaredConstructors(); for (Constructor declaredConstructor : declaredConstructors) { System.out.println(declaredConstructor); } System.out.println("=============================获取公有 & 无参的构造方法============================"); Constructor constructor = c.getConstructor(null); System.out.println(constructor); System.out.println("=============================获取公有 & 有参的构造方法============================"); Constructor constructor1 = c.getConstructor(new Class\[\]{String.class, Integer.class, String.class}); System.out.println(constructor1); System.out.println("=============================获取私有 & 有参 构造方法============================"); Constructor declaredConstructor1 = c.getDeclaredConstructor(new Class\[\]{String.class}); System.out.println(declaredConstructor1); }
}
结果:
2、获取类属性
public class Test02 {
public static void main(String\[\] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException { // 获取Class对象 Class<?> clazz = Class.forName("com.reflect.User"); System.out.println("=====获取所有的公共字段====="); Field\[\] fields = clazz.getFields(); for (Field field : fields) { System.out.println(field); } System.out.println("=====获取所有的字段(公开的、私有的)====="); Field\[\] declaredFields = clazz.getDeclaredFields(); for (Field declaredField : declaredFields) { System.out.println(declaredField); } System.out.println("=====获取公有字段并使用====="); // 获取指定公有字段 Field field = clazz.getField("name"); // 获取一个公有构造方法,然后实例化 Object obj = clazz.getConstructor().newInstance(); // 为属性设置值 field.set(obj, "张三"); // 测试,看设置的值是否成功 User user = (User) obj; System.out.println(user.getName()); System.out.println("=====获取私有字段并使用====="); Field field1 = clazz.getDeclaredField("sex"); // 获取构造函数,实例化对象 Object obj1 = clazz.getConstructor().newInstance(); // 暴力反射 field1.setAccessible(true); // 给属性设置值 field1.set(obj1, "男"); // 测试 User u = (User) obj1; System.out.println(u.getSex()); }
}
结果
这里需要注意,在获取私有属性的时候如果没有进行暴力反射,那么会抛出下面这个异常。
3、获取类中的方法
先定义几个方法
public void method1(String str) {
System.out.println("public 修饰的方法");
}
private void method2() {
System.out.println("private 修饰的方法");
}
String method3(String name, Integer age, String sex) {
System.out.println("默认修饰 " + name + " " + sex + " " + age + "岁"); return name + sex + age;
}
protected void method4() {
System.out.println("protected 修饰的方法");
}
正题
public class Test03 {
public static void main(String\[\] args) throws Exception { // 获取Class对象 Class<?> clazz = Class.forName("com.reflect.User"); System.err.println("======获取所有的public修饰的方法====="); Method\[\] methods = clazz.getMethods(); for (Method method : methods) { System.out.println(method); } Thread.sleep(1000); System.err.println("======获取所有的方法====="); Method\[\] declaredMethods = clazz.getDeclaredMethods(); for (Method declaredMethod : declaredMethods) { System.out.println(declaredMethod); } Thread.sleep(1000); System.err.println("======获取特定方法(带参)并使用====="); Method method1 = clazz.getMethod("method1", String.class); System.out.println(method1); Thread.sleep(1000); System.err.println("======获取特定方法(不带参)并使用====="); Method method2 = clazz.getDeclaredMethod("method2"); System.out.println(method2); System.err.println("======获取特定方法(多个参数)并使用====="); Method method3 = clazz.getDeclaredMethod("method3", String.class, Integer.class, String.class); // 获取构造方法,实例化一个对象 Object obj = clazz.getConstructor().newInstance(); // 给方法传值 Object invoke = method3.invoke(obj, "小涛", 24, "男"); // 测试 System.out.println(invoke); }
}
结果
这里需要注意的就是当一个方法需要传入多个参数值的时候,一定要注意。踩了一点坑。
四、反射执行main方法
public class Main {
public static void main(String\[\] args) { System.out.println("main方法执行了"); }
}
反射调用
public class Test04Main {
public static void main(String\[\] args) { try { // 获取Class对象 Class<?> clazz = Class.forName("com.reflect.Main"); // 获取Main方法 Method method = clazz.getMethod("main", java.lang.String\[\].class); // 调用 method.invoke(null, (Object) new String\[\]{"a"}); } catch (Exception e) { e.printStackTrace(); } }
}
这里需要告诉大家,在导String包的时候千万要看清楚,我在这填了20多分钟的坑。
五、总结
看到这里你已经对反射有了一个简单的了解,可以使用反射获取一些属性方法,其实我们平时写代码很少用到反射技术,但是在我们使用的一些主流框架中反射技术应用是非常广泛的,所以学好反射也是非常有必要的。
今天就写到这里,下篇给大家分享一下利用反射做一些有应用型的例子。
感觉不错就给小涛一个赞吧!
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
人工智能起步-反向回馈神经网路算法(BP算法)
人工智能分为强人工与弱人工。 弱人工智能就包括我们常用的语音识别,图像识别等,或者为了某一个固定目标实现的人工算法,如:下围棋,游戏的AI,聊天机器人,阿尔法狗等。 强人工智能目前只是一个幻想,就是自主意识,具有自我成长、创造力的AI。如妇联2里的奥创,各种电影都有这个概念了。 我希望不久的将来能目睹这一奇迹。 不积跬步无以至千里。 先从基础讲起。 目前比较先进的算法理论据我所知应该分成这几大类: 1,深度神经网络 2,生成对抗网络 3,深度强化学习 4,迁移学习 5,循环神经网络 神经元生物原理 100多年前脑部的生物构造被研究出来之后,大家就幻想可以通过模拟神经系统造人了。然后就弄出各种神经网络算法。所以先讲这部分内容,之后理解BP算法会更带感。 神经元是神经网络的基本单位,先贴一张图。 可以看到神经元的主要构造分为3个部分 N个树突+细胞体 +突触 神经元之间的连接是就是树突连接(另一个神经元)的突触。这种首尾相连的结构,N个树突可以连接N个神经元。 信号的传输方式是由N个神经元通过树突传递神经递质,递质上附加了生物电,当生物电累加到一定阙值时就会激发突触发送信号出去。 基本逻...
- 下一篇
selenium 结合 docker 构建分布式测试环境
随着自动化测试越学越深,深深觉得有太多的东西需要总结。 1.记录下学习中遇到的坑,当做学习笔记。 2.有前人路过看到文章中比较落后的做法,请务必一定要指教。(因为是初学者视角,很多东西只是走通而已,不足的地方多的去了,无论谁的指教都会让我受益匪浅) 3.因为我就是一个初学者,所以我打算详细的记录操作步骤,争取和我一样的初学者看着这篇文章就可以成功搭建测试环境。 项目背景: 我负责的自动化web测试框架已经搭建完成了。框架主要主要使用了: 语言:python 测试框架:pytest web自动化:selenium 报告框架:allure CI集成:jenkins 引入docker的目的: 优化自动化测试框架。当case在单个浏览器上走通了以后,就开始考虑是否需要考虑下兼容性,反正都是机器跑,跑一个浏览器是跑,跑二个也是跑。刚开始的时候打算用Selenium Standalone Server解决这个问题,但是在社区里看到了docker文章。立刻被吸引到了,通过docker 启动容器创建一个干净的测试环境,把外界因素对自动化测试的干扰降至最低。自动化测试稳定才是王道。 目标: 1.成功搭建...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS7,CentOS8安装Elasticsearch6.8.6
- CentOS8安装Docker,最新的服务器搭配容器使用
- SpringBoot2整合Redis,开启缓存,提高访问速度
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- MySQL8.0.19开启GTID主从同步CentOS8
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- CentOS7设置SWAP分区,小内存服务器的救世主