When to Use Class.forName vs. ClassLoader in Java? A Deep Dive
This article explains Java's reflection mechanisms, comparing Class.forName and ClassLoader as two primary ways to load classes, detailing their behavior, static initialization effects, code examples, and practical scenarios such as loading JDBC drivers versus custom dynamic loading.
In Java's reflection mechanism, Class.forName and ClassLoader are two important ways to load classes.
Class.forName
● It is a static method of java.lang.Class. By providing the fully qualified class name, it loads the class into the JVM at runtime.
● During loading, it triggers execution of the class's static initialization block. If the class name does not exist or cannot be accessed, a ClassNotFoundException is thrown.
package com.xuanwu.forNameOrClassLoader;
public class TestClass {
static {
System.out.println("这是静态代码块");
}
}
public class ClassTest {
public static void main(String[] args) throws ClassNotFoundException {
Class<?> aClass = Class.forName("com.xuanwu.forNameOrClassLoader.TestClass");
}
}
// Executing the above prints “这是静态代码块”ClassLoader
● It is an abstract class that serves as the core tool for class loading in Java. Every class is associated with a ClassLoader object responsible for loading class files into the JVM.
● The ClassLoader can dynamically load classes from various sources such as the local file system or network resources.
● As an abstract class, it requires concrete subclasses (e.g., URLClassLoader, AppClassLoader) to implement loading. Calling ClassLoader.loadClass loads a class without triggering its static initialization block; the block runs only when the class is first actively used.
package com.xuanwu.forNameOrClassLoader;
public class TestClass {
static {
System.out.println("这是静态代码块");
}
}
public class ClassLoaderTest {
public static void main(String[] args) throws ClassNotFoundException {
ClassLoader classLoader = ClassLoaderTest.class.getClassLoader();
Class<?> clazz = classLoader.loadClass("com.xuanwu.forNameOrClassLoader.TestClass");
System.out.println("=====加载类完毕=====");
try {
System.out.println("=====使用类=====");
clazz.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
}
}Use Cases and Summary
Class.forName
● The method’s functionality is fixed: it loads a class by name and executes static initialization. Its usage is limited to scenarios where immediate static initialization is required, such as loading database driver classes that register themselves with DriverManager.
try {
// Load database driver
Class.forName("com.mysql.cj.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}ClassLoader
● Provides a highly flexible class‑loading mechanism. By extending ClassLoader and overriding methods like loadClass, developers can implement custom loading logic, e.g., loading classes from encrypted files or remote servers.
● In most cases, especially when dynamic loading, custom class loading, or avoiding side effects of static initialization is needed, ClassLoader is recommended—for example, each web application in Tomcat has its own ClassLoader to support hot deployment and plugin architectures.
Xuanwu Backend Tech Stack
Primarily covers fundamental Java concepts, mainstream frameworks, deep dives into underlying principles, and JVM internals.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
