One of the things I like most about Java is its ability to load classes on demand. Given its interpreted nature, the virtual machine can detect when a class is not yet loaded and bring it to memory transparently; think of this as page faults and the MMU handling them.

Even more, you can ask it to load a specific class based on its name, which allows you to design powerful abstract models painlessly. Of course, you can do the same thing with C or C++, but things are trickier — dynamically loadable modules are not easy to deal with. (You could also use link sets.)

As an example, let's consider (a simplification of) a set of generic classes for unit testing that I've written as part of a university project:
  • Test: An abstract class to implement unit tests. Each class in the project will have another class dedicated to testing, which will inherit this one. For example, given a Foo class, there will be a TestFoo that does whatever is appropriate to ensure that Foo works.
  • Tester: A generic driver that, based on commands given in the standard input, loads the appropriate test class, runs its unit tests and verifies the results based on prerecorded (correct) output values.
The thing is: how do you get a Tester class that is completely independent of, say, TestFoo? Ideally, Tester should only know the Test class and nothing else. Here is where dynamic class loading comes to help.

The Tester class receives a class name (Foo in our example) on the program's standard input, among a set of arguments that describe the unit test to be executed. Based on this name, it tries to load its corresponding testing class and, if it succeeds, it executes the appropriate methods. This is only possible because all testing classes have Test as the common ancestor.

As a code example, assume a className variable that holds the name read from standard input and a opName variable that has the name of the operation to be tested:
String className, opName;
/* Read className and opName from stdin. */
try {
Class c = Class.forName("Test" + className);
Test t = (Test)c;
t.execute(opName);
} catch (Exception e) {
/* Catching Exception for simplicity. */
}
It is up to your imagination how you use this feature, but, as you can see, it is extremely useful.

Comments from the original Blogger-hosted post: