The core differences between the three approaches come down to how the classes are located at runtime and what you can do with them.
For example...
Class.forName("test.Employee").newInstance();
Will use the current class's ClassLoader
to search the class named Employee
in the test
package. This would allow you to discover classes that might not be available at compile time and which are loaded dynamically into the same class loader context. This will also search it's parent class loaders if the class is not found within the current context...
ClassLoader.getSystemClassLoader().loadClass("test.Employee").newInstance();
This will use the "system" ClassLoader
, this typically the one that launched the main application.
Using either of these two methods is a great way to generate dynamic applications where the actual implementation of a Class
is not known at compile type. The problem here is it can affect visibility and restrict what you can do with the loaded classes.
For example, while you may have loaded the test.Employee
class and created an instance of it, unless you have a reference to test.Employee
at compile time, you want be able to cast it. This is typically where interface
s come in very handy.
Equally, you could create your own ClassLoader
instance and load classes or jars at runtime to provide, for example, plugins, factories or managers where the implementation is unknown at compile time. The functionality for these would, typically, be described through the use of interface
s.
Examples would include java.awt.Toolkit
and JDBC java.sql.Driver
At the end of the day, the ClassLoader
mechanism is providing a means by which a class file can be loaded and instantiated into the current JVM. The new
keyword does a similar job, but the results are pre-determined at compile time
ClassLoader
s are a very powerful feature and provide a lot of functionality, but can also be down right confusion, especially the way that they chain together
You might find...
of some help