Class.forName 会初始化类,ClassLoader.loadClass 不会初始化类;前者触发静态块执行,后者仅加载字节码;需初始化时用前者,仅加载时用后者。

选择 Class.forName 还是 ClassLoader.loadClass,关键看是否需要**触发类的初始化(即执行 static 代码块和静态变量赋值)**。前者默认会初始化,后者默认不初始化。
需要初始化时用 Class.forName
当你加载类后要立即使用它(比如获取 Class 对象后调用 newInstance()、反射调用静态方法、或依赖其静态字段),且该类的静态初始化逻辑必须执行,就该用 Class.forName。
- 它内部调用的是当前类的类加载器,并传入
true表示启用初始化 - 等价于
Class.forName(className, true, currentClassLoader) - 典型场景:JDBC 驱动注册(老版本)、Spring 的某些早期加载逻辑
避免初始化时用 ClassLoader.loadClass
如果你只是想确认类存在、获取 Class 对象但暂时不用其实例或静态成员,或者想延迟初始化(比如按需加载、避免启动时副作用),就该用 ClassLoader.loadClass。
- 它不会触发类的初始化,只完成加载和链接(验证、准备)
- 适合做类型检查、生成代理、框架元数据扫描等轻量操作
- 若后续确实要用,可手动调用
Class.forName(className, true, loader)或访问某个静态字段来触发初始化
注意类加载器的来源差异
Class.forName(String) 使用**当前类的类加载器**(即定义调用该方法的类的那个加载器);而 ClassLoader.loadClass 必须显式指定加载器,更灵活但也更易出错。
立即学习“Java免费学习笔记(深入)”;
- 如果跨模块或使用自定义类加载器,推荐直接用
yourClassLoader.loadClass(...),避免隐式依赖上下文 - 在 Servlet 或 OSGi 环境中,混用可能导致
ClassNotFoundException,因为类加载器委托链不同
Java 9+ 的建议:优先用 ClassLoader 的重载方法
Java 9 引入了 ClassLoader.getSystemClassLoader().loadClass(String) 和更明确的 Class.forName(String, boolean, ClassLoader),语义更清晰。
- 显式传入
false控制初始化,比默认行为更可控 - 避免因 JDK 版本或上下文类加载器变化导致行为不一致
- 框架开发中建议封装统一的类加载策略,而不是零散调用这两个 API


















