# 反射的概述
- 反射是框架设计的灵魂。
- 反射是一种在运行时动态获取类的信息并操作类的属性、方法和构造函数的技术。
- 它允许程序在运行时动态地获取类的信息并操作类的属性、方法和构造函数等。
# 反射的简介
- 反射是
Java
编程语言中一种强大的机制,它允许程序在运行时动态地获取类的信息并操作类或对象。 - 通过反射,我们可以在运行时获取类的属性、方法、构造函数等,并且可以动态调用这些成员。
- 这种能力使得我们可以在事先不知道类的情况下,通过运行时获取类的信息并进行相关操作。
Java
反射提供了以下几个重要的类和接口:Class
类:它是反射的核心类,代表了一个类的信息,可以获取类的属性、方法、构造函数等。Field
类:它表示类的成员变量(属性),可以通过它获取和设置成员变量的值。Method
类:它表示类的方法,可以通过它调用类的方法。Constructor
类:它表示类的构造函数,可以通过它创建类的实例。
- 通过反射,我们可以实现一些灵活的功能,比如动态创建对象、调用私有方法、访问私有属性等。
- 但需要注意的是,由于反射涉及到底层的操作,使用不当可能会影响性能,并且也会破坏了面向对象的封装性。
# 反射的原理
反射机制的实现依赖于 Java
的类加载机制。 在 Java
中,每个类都必须通过 ClassLoader
类来加载,而 ClassLoader
类又分为三种类型: BootStrap ClassLoader
、 Extension ClassLoader
和 Application ClassLoader
。当一个类被加载时, Java
虚拟机会根据类的全限定名找到相应的 ClassLoader
来加载类文件,并将其转换为 Class
对象。
# 反射应用场景
- 例如:
- 动态创建对象:通过反射机制可以在运行时动态地创建对象,而不需要提前知道类的具体信息。
- 动态调用方法:通过反射机制可以在运行时动态地调用对象的方法,而不需要提前知道方法的具体名称和参数。
- 获取类的属性和方法:通过反射机制可以在运行时动态地获取类的属性和方法,包括属性的名称、类型、修饰符等等。
- 操作类的注解:通过反射机制可以获取类的注解信息,并进行相应的处理。
- 实现代理和适配器:通过反射机制可以动态地生成代理和适配器,实现对现有类的扩展和修改。
- 由于反射机制需要在运行时动态地获取类的信息,因此会带来一定的性能开销和安全风险。
- 反射机制虽然强大,但也有一些限制和缺,此外,反射机制也容易被误用,导致代码难以维护和调试。
# 反射使用步骤
- 获取
Class
对象:使用 Class.forName()
或 ClassLoader.loadClass()
方法获取一个类的 Class
对象。 - 获取类的成员信息:使用
Class
类的 getDeclaredFields()
、 getDeclaredMethods()
和 getDeclaredConstructors()
方法获取类的成员信息,包括字段、方法和构造方法。 - 访问类的成员:使用
Class
类的 getField()
、 getMethod()
和 getConstructor()
方法获取类的成员对象,然后使用成员对象的相应方法访问类的属性、方法和构造函数。 - 调用类的方法:使用
Method
类的 invoke()
方法调用类的方法,并传递相应的参数。 - 创建类的实例:使用
Class
类的 newInstance()
方法创建类的实例。
# 反射的使用
# 反射获取字段
Person.java | |
| * @Author: LightRain |
| * @Description: Bean 对象 |
| * @DateTime: 2023-08-29 18:08 |
| * @Version:1.0 |
| **/ |
| public class Person { |
| private String name; |
| private int age; |
| private String address; |
| } |
ReflectDemo.java | |
| * @Author: LightRain |
| * @Description: 使用反射获取 Bean 对象中的字段 |
| * @DateTime: 2023-08-29 16:04 |
| * @Version:1.0 |
| **/ |
| public class ReflectDemo { |
| public static void main(String[] args) { |
| |
| Class<?> clazz = Person.class; |
| |
| Field[] fields = clazz.getDeclaredFields(); |
| |
| for (Field field : fields) { |
| System.out.println(field.getName()); |
| } |
| } |
| } |
# 反射获取 Get 方法
Person.java | |
| * @Author: LightRain |
| * @Description: Bean 对象 |
| * @DateTime: 2023-08-29 18:08 |
| * @Version:1.0 |
| **/ |
| public class Person { |
| private String name; |
| private int age; |
| private String address; |
| |
| public String getName() { |
| return name; |
| } |
| |
| public void setName(String name) { |
| this.name = name; |
| } |
| |
| public int getAge() { |
| return age; |
| } |
| |
| public void setAge(int age) { |
| this.age = age; |
| } |
| |
| public String getAddress() { |
| return address; |
| } |
| |
| public void setAddress(String address) { |
| this.address = address; |
| } |
| } |
ReflectDemo.java | |
| * @Author: LightRain |
| * @Description: 使用反射获取 Bean 对象中的所有 get 方法和参数 |
| * @DateTime: 2023-08-29 16:04 |
| * @Version:1.0 |
| **/ |
| public class ReflectDemo { |
| public static void main(String[] args) throws NoSuchFieldException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { |
| |
| Person person = new Person(); |
| person.setName("张三"); |
| person.setAge(16); |
| person.setAddress("..."); |
| |
| Class<?> clazz = Person.class; |
| Method[] methods = clazz.getDeclaredMethods(); |
| Method[] getMethods = Arrays.stream(methods) |
| .filter(method -> Modifier.isPublic(method.getModifiers()) && method.getReturnType() != void.class && method.getName().startsWith("get")) |
| .toArray(Method[]::new); |
| |
| |
| for (Method method : getMethods) { |
| Object result = method.invoke(person); |
| System.out.println(method.getName() + " = " + result); |
| } |
| } |
| } |