What is the difference between "Class.forName()" and "Class.forName().newInstance()"?
Categories:
Class.forName() vs. Class.forName().newInstance(): Understanding Java Class Loading and Instantiation

Explore the fundamental differences between Class.forName()
and Class.forName().newInstance()
in Java, their use cases, and implications for class loading and object creation.
In Java, dynamically loading and instantiating classes at runtime is a powerful feature. Two common methods for achieving this are Class.forName(String className)
and Class.forName(String className).newInstance()
. While they appear similar, their functionalities and implications are distinct. Understanding these differences is crucial for writing robust and efficient Java applications, especially when dealing with reflection, JDBC drivers, or plugin architectures.
Class.forName(): Loading and Initializing a Class
The Class.forName(String className)
method is primarily used to load a class into the Java Virtual Machine (JVM) and, by default, initialize it. When you call Class.forName()
, the JVM performs several actions:
- Loads the class: It finds the
.class
file corresponding to the given class name and loads its bytecode into memory. - Links the class: This involves verifying the bytecode, preparing static fields with default values, and optionally resolving symbolic references.
- Initializes the class: This is the most significant part. The JVM executes any static initializers (static blocks) and initializes static fields with their declared values. This step happens only once per classloader for a given class.
It's important to note that Class.forName()
returns a Class<?>
object, which represents the class itself, not an instance of that class. The class is loaded and initialized, but no object of that class is created.
public class MyClass {
static {
System.out.println("MyClass static initializer executed.");
}
public MyClass() {
System.out.println("MyClass constructor executed.");
}
public void doSomething() {
System.out.println("MyClass instance method called.");
}
public static void main(String[] args) throws ClassNotFoundException {
System.out.println("Before Class.forName()");
Class<?> clazz = Class.forName("MyClass");
System.out.println("After Class.forName(): Class object obtained: " + clazz.getName());
// No object is created yet
}
}
Example demonstrating Class.forName() loading and initialization
Class.forName(String name, boolean initialize, ClassLoader loader)
, allows you to control whether the class is initialized immediately. Setting initialize
to false
will load and link the class but defer its initialization until it's actively used.Class.forName().newInstance(): Loading, Initializing, and Instantiating
The expression Class.forName(String className).newInstance()
does everything Class.forName()
does, and then it goes a step further: it creates a new instance of the loaded class. Specifically:
- Loads, links, and initializes the class: This is identical to the
Class.forName()
behavior described above. - Instantiates the class: After the class is loaded and initialized,
newInstance()
calls the class's public no-argument constructor to create a new object. If the class does not have an accessible no-argument constructor, it will throw anInstantiationException
orIllegalAccessException
.
This method is a convenient way to create objects dynamically when you don't know the exact class type at compile time, but you know it will have a default constructor.
public class MyClass {
static {
System.out.println("MyClass static initializer executed.");
}
public MyClass() {
System.out.println("MyClass constructor executed.");
}
public void doSomething() {
System.out.println("MyClass instance method called.");
}
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
System.out.println("Before Class.forName().newInstance()");
Object obj = Class.forName("MyClass").newInstance();
System.out.println("After Class.forName().newInstance(): Object created: " + obj.getClass().getName());
((MyClass) obj).doSomething();
}
}
Example demonstrating Class.forName().newInstance() for loading, initializing, and instantiating
Class.newInstance()
method is deprecated since Java 9. The preferred way to create a new instance using reflection is to use Class.getDeclaredConstructor().newInstance()
, which offers more control over constructor arguments and access levels.Key Differences and Use Cases
The core distinction lies in whether an object instance is created. Class.forName()
only prepares the class for use, while Class.forName().newInstance()
also creates an object. This leads to different use cases:
Class.forName()
Use Cases:- JDBC Driver Registration: Historically,
Class.forName("com.mysql.cj.jdbc.Driver")
was used to register JDBC drivers. The driver's static initializer would register the driver withDriverManager
. Modern JDBC drivers often use the Service Provider Interface (SPI) mechanism, making explicitClass.forName()
calls less common. - Triggering Static Initializers: If you need to ensure a class's static block is executed without necessarily creating an object,
Class.forName()
is suitable. - Obtaining Class Metadata: When you only need to inspect a class's structure (fields, methods, annotations) without creating an instance.
- JDBC Driver Registration: Historically,
Class.forName().newInstance()
Use Cases:- Dynamic Object Creation: When you need to create an object of a class whose type is determined at runtime (e.g., from a configuration file or user input).
- Plugin Architectures: Loading and instantiating plugin classes dynamically.
- Frameworks: Many frameworks use this pattern to instantiate components based on configuration.
flowchart TD A[Start] B{Call Class.forName("MyClass")?} C{Call Class.forName("MyClass").newInstance()?} D[Load Class Bytecode] E[Link Class] F[Initialize Class (Execute Static Blocks)] G[Return Class<?> Object] H[Call Public No-Arg Constructor] I[Return New Object Instance] J[End] A --> B B -- Yes --> D B -- No --> C C -- Yes --> D C -- No --> J D --> E E --> F F --> G G --> J F --> H H --> I I --> J
Flowchart illustrating the execution paths of Class.forName() and Class.forName().newInstance()
Class.forName().newInstance()
is convenient, using Class.getDeclaredConstructor().newInstance()
is generally preferred in modern Java reflection for its flexibility in handling constructors with arguments and better error handling.