Java 反射Class.forName()

问题

为什么反射加载不知道的类,在使用Class.forName()方法时,需要指定一个类的名称,那这不就是知道了类吗?

当我们使用new关键字创建对象时,我们的代码必须知道具体的类,编译器会在编译时检查这个类是否存在,这种方式是静态的,在编译时就需要确定所有的类和对象。但是,当我们使用反射时,我们可以在程序运行时才决定使用哪个类,这样程序就可以更加灵活地响应在编译时无法预知的变化。

使用Class.forName()的典型场景包括:

  • 插件系统:应用程序可以加载不同的插件,而这些插件的具体类在编译时是不确定的。
  • 配置驱动的应用程序:类的名称可以从配置文件中读取,程序根据配置来加载对应的类。
  • 动态代理:在运行时创建接口的代理实例,这些接口的实现类是在运行时确定的。
  • 数据库驱动加载:JDBC中经常使用Class.forName()来动态加载数据库驱动。

在这些情况下,尽管我们使用Class.forName()时知道要加载的类名,但这个类名很可能是用户输入、配置文件、或者网络传输等在程序运行时才能确定的信息,而不是在编写代码时就能固定的。因此,反射提供了一种运行时动态处理类的机制,增加了程序的灵活性和扩展性。

一般情况下,我们使用某个类时必定知道它是什么类,是用来做什么的。于是我们直接对这个类进行实例化,之后使用这个类对象进行操作

假如我们有一个插件系统,让用户自己选择使用那些插件(类),所以我们不知道要加载那些类

使用一个变量作为参数传给Class.forName()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import java.util.Scanner;

public class DynamicLoader {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入要加载的类名:");
String className = scanner.nextLine();

try {
Class<?> clazz = Class.forName(className);
// 假设这个类有一个无参的构造方法
Object instance = clazz.getDeclaredConstructor().newInstance();
// 接下来可以使用instance来调用类的方法等
System.out.println("类已加载并实例化:" + instance.getClass().getName());
} catch (ClassNotFoundException e) {
System.err.println("找不到指定的类:" + className);
} catch (Exception e) {
e.printStackTrace();
} finally {
scanner.close();
}
}
}