Class.forName 和 ClassLoader 有什么区别?¶
结论¶
Class.forName(name) |
ClassLoader.loadClass(name) |
|
|---|---|---|
| 默认行为 | 加载 + 链接 + 初始化(执行 static 块) | 只加载,连接和初始化延迟到首次主动使用 |
| 类加载器 | 默认用调用者的 ClassLoader | 可指定任意 ClassLoader |
| 典型场景 | JDBC 驱动注册、Spring 反射 | 自定义类加载、热部署 |
详细对比¶
Class.forName¶
默认调用 Class.forName(className, true, currentClassLoader),第二个参数 true 表示 initialize,会触发:
- 验证、准备、解析(连接)
- 执行
<clinit>,即 static 变量赋值与 static 代码块
这就是 JDBC 4.0 之前必须 Class.forName("com.mysql.jdbc.Driver") 的原因——Driver 类的 static 块里会把自己注册到 DriverManager。
ClassLoader.loadClass¶
只做"加载"阶段:读取 class 字节流、生成 Class 对象。不执行 static 块,直到:
- 创建实例
new Foo() - 调用静态方法
- 访问静态字段
- 反射
Class.newInstance()
何时用哪个¶
- JDBC 驱动:用
Class.forName(旧版),因为要触发 static 注册。 - SPI / 插件加载:用
loadClass,延迟初始化以节省启动时间。 - Spring 的
@ConditionalOnClass:用loadClass,只判断类是否存在,不希望触发初始化副作用。