一、反射概述
1.什么反射
Java的反射(reflection)机制是指在程序的运行状态中,借助 Reflection API 取得任何类的内部信息,可以动态地构造任意一个类的对象,并能直接操作任意对象的属性和方法。这种动态获取程序信息以及动态调用对象的功能称为Java语言的反射机制。反射被视为动态语言的关键。

2.反射的原理
从内存角度理解:一个类被JVM加载后,在堆内存的方法区中就生成一个该类对应的Class(java.lang.Class)类型的对象,并且一个类只有一个Class对象。这个Class对象就包含了该类的完整结构信息,这个Class对象就像该类的一面镜子,通过镜子我们可以看到该类的结构信息,所以形象的称之为反射。
3.反射的优缺点
优点:
-
动态性:反射可以在运行时动态地获取和操作类的信息,而不需要在编译时知道类的具体细节。这使得程序能够更加灵活地处理不同的类和对象。
-
扩展性:反射使得程序能够处理未知的类和对象。它可以在运行时动态地加载、创建和操作类,从而实现各种扩展和插件机制。
-
动态代理:反射为实现动态代理提供了基础。通过反射,程序可以在运行时创建代理对象并拦截方法调用,从而实现额外的功能。
缺点:
-
性能损失:由于反射需要在运行时检查和操作类的信息,在某些情况下会比直接使用静态调用更慢。因此,在需要高性能的场景下,应尽量避免过多地使用反射。
-
安全性问题:反射可以访问和修改类的私有成员,这可能会破坏封装性和安全性。因此,使用反射时需要谨慎地处理权限和安全性相关的问题。
-
破坏编译时检查:反射可以绕过编译时的类型检查,导致一些潜在的错误在运行时才被发现。这增加了代码的难以维护和调试的复杂性。
反射强大的灵活性特性,它为程序提供了动态性和扩展性,特别在框架和库的开发中非常有用。然而,反射也需要谨慎使用,避免性能和安全性问题,并且不应该滥用以避免破坏编译时检查。
二、反射机制提供的功能
Java反射的主要功能包括以下几个方面:
- 运行时获取类的信息:Java反射可以在运行时获取类的名称、父类、实现的接口、字段、方法和构造函数等信息。
-
动态加载类和创建实例:Java反射可以在运行时根据类的名称动态加载类,并创建类的实例。
-
动态调用方法:Java反射可以在运行时通过方法对象动态调用类的方法,包括公开方法、私有方法和静态方法。
-
动态访问和设置属性:Java反射可以在运行时通过字段对象动态访问和设置类的属性,包括公开属性、私有属性和静态属性。
-
动态生成代理对象:Java反射可以在运行时通过代理类生成代理对象,实现动态代理的功能。
-
动态修改类的行为:Java反射可以在运行时修改类的行为,例如通过修改方法的访问级别、替换方法的实现等。
三、反射的基本用法
1.获取Class类对象
获取Class对象有三种方法:
- 类实例.getClass() : 已知类的实例,通过该实例调用getClass()方法获取。
- Class.forName("全类名") : 已知一个类的全类名,且该类在类路径下,可通过Class类的静态方法forName()获取,该方法可能会抛出 ClassNotFoundException 异常。
- 类名.class : 若已知具体的类,通过类的class属性获取,该方法最安全可靠,程序性能最高。
代码演示:
public static void main(String[] args) throws ClassNotFoundException {
//获取Class对象的三种方式
// 方式一:通过对象获取(Object类中的getClass()方法)
Person person = new Person();
Class c1 = person.getClass();
System.out.println(c1);
// 方式二:通过Class类的forName获取
Class c2 = Class.forName("com.example.reflection.Person");
System.out.println(c2);
// 方式三:通过类名.class属性获取
Class c3 = Person.class;
System.out.println(c3);
//三种方式获取的Class对象是同一个
System.out.println(c1 == c2&&c2 == c3);
}
并且三种方式获取的Class对象是同一个,因为一个类只有一个Class对象,运行结果如下:

最低0.47元/天 解锁文章
1834

被折叠的 条评论
为什么被折叠?



