Class.forName会立即初始化类并执行静态代码块,ClassLoader.loadClass仅加载类不触发初始化;前者用于JDBC驱动注册等需立即执行静态逻辑的场景,后者适用于插件热加载等懒初始化需求。
Class.forName 会立即执行静态代码块,loadClass 不会
这是最直接可观察的差异。当你调用
,JVM 在加载类后立刻进入「初始化」阶段,执行所有
块和静态字段赋值;而
只走到「加载」+「链接」阶段,静态代码块原封不动,直到你第一次访问它的静态成员、new 实例或调用其静态方法时才触发初始化。
常见错误现象:用
加载 JDBC 驱动类(如
),结果
报
——因为驱动类的静态注册逻辑没跑。
必须用
的场景:JDBC 驱动注册、SPI 服务发现中需立即触发静态注册逻辑的类
适合用
的场景:插件系统、热更新模块、仅需获取
对象做元信息分析(比如扫描注解),不希望提前触发副作用
注意:
的第二个参数
默认为
,即使设为
也只影响「链接」阶段(验证、准备、解析),仍不触发「初始化」
异常处理方式不同:抛异常 vs 返回 null
找不到类或加载失败时,直接抛出
;
在父加载器无法加载且自身也无法加载时,**返回
**,而不是抛异常——这点极易被忽略,导致 NPE 或静默失败。
使用场景上:
更适合“类必须存在且可用”的强依赖路径;
更适合试探性加载(比如按策略尝试多个类名),但你要自己判空并兜底。
别对
的返回值不做非空检查就直接调用
或
的异常是受检异常,必须 try-catch 或 throws;
的异常只在后续真正使用类时才可能爆发(如
),排查更困难
类加载器来源不一致,影响双亲委派行为
默认使用当前线程上下文类加载器(
),若未显式设置,通常是应用类加载器;而
是实例方法,你必须先拿到一个
实例(比如
),它取决于你从哪个类出发获取——这可能导致加载器层级不同,进而影响双亲委派结果。
典型问题:Web 应用中,用
加载某个 jar 包里的类成功,但用
却失败,原因就是前者用了线程上下文类加载器(能看见 WEB-INF/lib),后者用了当前类的类加载器(可能被隔离)。
如果需要确保加载器一致,显式传参:
不要假设
总是返回你期望的那个加载器;调试时可打印
和
确认链路
为什么「显式初始化」这个动作不能省略
Java 类加载的「初始化」阶段不是可选步骤,而是语义必需——它保证静态常量(
)被正确赋值、静态资源被预加载、全局状态被建立。绕过它,等于跳过契约。
最容易被忽略的点:编译期常量(如
)在编译时就被内联进调用处,即使类从未初始化,也能“看起来正常”;但一旦涉及运行期计算的静态字段(
)或静态块中的 I/O、注册、缓存填充,漏掉初始化就会导致逻辑断裂,且问题往往延迟暴露。
所以,别把「类已加载」等同于「类已就绪」——加载(Loading)和初始化(Initialization)是两个独立阶段,
和
的分水岭正在于此。
Class.forName("com.example.TestClass")static{}classLoader.loadClass("com.example.TestClass")loadClass"com.mysql.cj.jdbc.Driver"DriverManager.getConnection()No suitable driver foundClass.forNameloadClassClassloadClassresolvefalsetrueClass.forNameClassNotFoundExceptionClassLoader.loadClassnullClass.forNameloadClassloadClass.newInstance().getDeclaredMethods()Class.forNameloadClassNoClassDefFoundErrorClass.forName(String)Thread.currentThread().getContextClassLoader()ClassLoader.loadClassClassLoaderMyClass.class.getClassLoader()Class.forNamegetClassLoader().loadClassClass.forName(name, true, classLoader)getClassLoader()loader.getClass().getName()loader.getParent()public static finalpublic static final int VAL = 123;public static final long TS = System.currentTimeMillis();Class.forNameClassLoader.loadClass