Course – LS (cat=Java)

Get started with Spring 5 and Spring Boot 2, through the Learn Spring course:


1. Overview

In Java, dynamic loading of classes involves loading a class into the Java Virtual Machine at runtime instead of compile time. This method proves beneficial in situations where we don't know the names of the classes at compile time, or when class loading is based on user input or system properties.

There are several ways to dynamically load classes in Java, including the Class.forName() method, the ClassLoader API, and Dependency Injection frameworks.

In this article, we'll consider Class.forName() and Class.forName().newInstance() methods, which are commonly used in Java applications and are essential for developers to understand.

2. The Class.forName() Method

The Class.forName() method takes a fully qualified name of the class as an argument and returns a Class object associated with the loaded class. During execution, it attempts to locate, load, and link the class or interface. It's generally used when we want to get information about a class, such as fields and methods. We should note, however, that the class isn't initialized, and calling its methods is impossible.

Let's write a quick test that uses the Class.forName() method:

public void whenUseClassForNameCreatedInstanceOfClassClass() throws... {
   Class instance = Class.forName("com.baeldung.loadclass.MyClassForLoad");
   assertInstanceOf(Class.class, instance, "instance should be of Class.class");

It's also important to remember that the dynamic loading method doesn't verify the accessibility of the requested class to its caller, leading to potential exceptions related to loading, linking, or initializing. Handling them properly is crucial to avoid unexpected behavior and potential crashes:

  • LinkageError – if the linkage fails
  • ExceptionInInitializerError – if the initialization fails
  • ClassNotFoundException – if it can't find the class

3. The Class.forName().newInstance() Method

The Class.forName().newInstance() method is appropriate when we want to create an instance of a class. This method also takes as an argument a fully qualified name of the class and returns a new instance of the class represented by this Class object. It's like calling a new operator for MyClassForLoad with an empty arguments list.

Let's see an example of using the Class.forName().newInstance() method in a unit test:

public void whenUseClassForNameWithNewInstanceCreatedInstanceOfTargetClass throws... () {
   Object instance = Class.forName("com.baeldung.loadclass.MyClassForLoad").newInstance();
   assertInstanceOf(MyClassForLoad.class, instance, "instance should be of MyClassForLoad.class");

Keep in mind that Class.forName().newInstance() potentially can throw one of several exceptions:

  • IllegalAccessException – if the class or its nullary constructor is not accessible
  • InstantiationException – if this class represents an abstract class, an interface, an array class, a primitive type, or void
  • ExceptionInInitializerError – if the initialization provoked by this method fails
  • SecurityException – when the calling code doesn't have sufficient permissions to access the specified class

However, it's important to note that newInstance() has been deprecated since Java 9 because it propagates any exception thrown by the nullary constructor, including a checked exception. This method effectively bypasses the compile-time exception checking performed by the compiler. As a result, it can lead to unexpected errors or bugs and a less robust and maintainable codebase.

It's recommended to call the getDeclaredConstructor().newInstance() construction that avoids this problem:

Object instance = Class.forName("com.baeldung.loadclass.MyClassForLoad").getDeclaredConstructor().newInstance();

4. Conclusion

Developers must have a strong understanding of how dynamic class loading works in Java. It provides many benefits that can help to improve the performance, maintainability, and scalability of Java applications.

In this article, we learned that Class.forName() and Class.forName().newInstance() are two crucial methods in Java that allow us to load classes at runtime. The difference between the methods lies in what they do and what they return. 

Class.forName() loads a class dynamically and returns a Class object, while Class.forName().newInstance() loads a class and creates an instance of the loaded class.

Understanding these methods and their differences is essential, as they are often used in real-world scenarios: 

  • Plugins development
  • Dependency Injection frameworks like Spring or Guice
  • Loading JDBC Drivers based on the database being used
  • Loading classes based on input parameters

Finally, by knowing the difference between Class.forName() and Class.forName().newInstance(), developers can make informed decisions about how to load classes dynamically in their Java projects, leading to more efficient and effective code.

The full source is available over on GitHub.

Course – LS (cat=Java)

Get started with Spring 5 and Spring Boot 2, through the Learn Spring course:

res – REST with Spring (eBook) (everywhere)
Comments are closed on this article!