文章目录
- 前言
- 一、反射机制
- 二、反射的用途
- 三、反射相关的类(重要)
- 3.1 Class类(反射机制的起源 )
- 3.2 通过反射调用构造方法
- 3.3 通过反射调用普通方法
- 3.4 通过反射调用类属性
- 四、反射的优缺点
- 总结
前言
博主个人社区:开发与算法学习社区 博主个人主页:Killing Vibe的博客 欢迎大家加入,一起交流学习~~
一、反射机制
反射:在JVM运行时,一切框架的基础。
对于JVM中任何一个类,都能动态获取该类的所有属性和方法。
对于JVM中的任何一个对象,都能动态调用该对象的属性和方法。
动态获取信息以及调用对象机制称为反射机制
二、反射的用途
1、在日常的第三方应用开发过程中,经常会遇到某个类的某个成员变量、方法或是属性是私有的或是只对系统应用开放,这时候就可以利用Java的反射机制通过反射来获取所需的私有成员或是方法 。 2、反射最重要的用途就是开发各种通用框架,比如在spring中,我们将所有的类Bean交给spring容器管理,无论是XML配置Bean还是注解配置,当我们从容器中获取Bean来依赖注入时,容器会读取配置,而配置中给的就是类的信息,spring根据这些信息,需要创建那些Bean,spring就动态的创建这些类。
拓展:
Java程序中许多对象在运行时会出现两种类型:运行时类型(RTTI)和编译时类型,例如Person p = new Student();这句代码中p在编译时类型为Person,运行时类型为Student。程序需要在运行时发现对象和类的真实信息。而通过使用反射程序就能判断出该对象和类属于哪些类。
运行时明确该引用到底是啥类型就可以通过反射机制。
三、反射相关的类(重要)
这些类都在java.lang.reflect包下面。
1.Class类: 反射核心类,使用class关键字,包括数组,包括接口编译后生成的class文件就对应一个唯一的class对象,由JVM产生,使用这个class对象就可以获取该类的所有信息。
例如定义如下一个学生类:
代码语言:javascript复制class Student{
int age;
String name;
}
执行 javac Student.java 后 => Student.class
将JVM启动之后,Student类被加载到JVM之后就会产生一个全局唯一的Student.class对象,由JVM产生,就根据这个对象来反射操作Student类
2.Field类:反射调用类中的成员/类属性
3.Method类:反射调用类中的成员/类方法
4.Constructor类:反射调用构造方法
3.1 Class类(反射机制的起源 )
Java文件被编译后,生成了.class文件,JVM此时就要去解读.class文件 ,被编译后的Java文件.class也被JVM解析为一个对象,这个对象就是 java.lang.Class .这样当程序在运行时,每个java文件就最终变成了Class类对象的一个实例。我们通过Java的反射机制应用到这个实例,就可以去获得甚至去添加改变这个类的属性和动作,使得这个类成为一个动态的类 .
无论要通过反射机制干啥事情,首先第一步就是获取该类的class对象(由JVM产生的,全局唯一)
三种方式:
- 调用Class.forName(类的全名称) 【包名.类名】
- 调用类名称.class 【属性】
- 通过该类的任意对象的getClass()
3.2 通过反射调用构造方法
普通的get只能获取public权限的方法或者属性,getDeclared…()可以获取所有权限的方法或属性
示例:
代码语言:javascript复制 // 1.获取所有public权限的构造方法
Constructor[] constructors = cls.getConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
System.out.println("------------------------------");
// 获取该类所有构造方法
Constructor[] constructors1 = cls.getDeclaredConstructors();
for (Constructor constructor : constructors1) {
System.out.println(constructor);
}
破坏封装产生对象:
代码语言:javascript复制// 破坏封装,通过反射破坏private封装,调用私有构造方法
constructor.setAccessible(true);
Student student = constructor.newInstance("Killing Vibe");
System.out.println(student);
3.3 通过反射调用普通方法
invoke方法:
示例:
假设已经获取了Student类的反射对象cls,Student类中有一个test方法
代码语言:javascript复制 //2.获取要调用方法的Method对象
Method method1 = cls.getDeclaredMethod("test");
// test是静态方法,无需产生Student对象
method1.invoke(null);
Method method2 = cls.getDeclaredMethod("fun",String.class);
Student student = new Student("VIBE","男",18);
method2.invoke(student,"传入的参数");
3.4 通过反射调用类属性
Field.get()方法 : 通过obj对象获取相关属性的值,属性为静态属性,则传入null
Field.set()方法:通过obj对象修改相关属性的值,若为静态对象,则传入null
示例:
假设已经获取了Student类的反射对象cls,Student类中有country,age属性
代码语言:javascript复制 // 3.获取要拿到的属性Field对象
Field field = cls.getDeclaredField("country");
System.out.println(field.get(null));
Field field1 = cls.getDeclaredField("age");
Student student = new Student("VIBE","男",18);
System.out.println(field1.get(student));
field1.set(student,20);
System.out.println(field1.get(student));
运行如下:
四、反射的优缺点
优点:
- 对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法
- 增加程序的灵活性和扩展性,降低耦合性,提高自适应能力
- 反射已经运用在了很多流行框架如:Struts、Hibernate、Spring 等等。
缺点:
- 使用反射会有效率问题。会导致程序效率降低。
- 反射技术绕过了源代码的技术,因而会带来维护问题。反射代码比相应的直接代码更复杂 。
总结
以上就是Java反射机制的原理以及相关类和代码实现,如果有什么疑问或者需要完整代码可以私信博主~~感谢支持