Difference between Class.forName() and ClassLoader.loadClass()

来源:互联网 发布:微信编辑器php源代码 编辑:程序博客网 时间:2024/05/16 00:56

Both methods try to dynamically locate and load ajava.lang.Class object corresponding to a given class name. However, their behavior differs regarding whichjava.lang.ClassLoader they use for class loading and whether or not the resulting Class object is initialized.

The most common form of Class.forName(), the one that takes a single String parameter, always uses the caller's classloader. This is the classloader that loads the code executing the forName() method. By comparison, ClassLoader.loadClass() is an instance method and requires you to select a particular classloader, which may or may not be the loader that loads that calling code. If picking a specific loader to load the class is important to your design, you should useClassLoader.loadClass() or the three-parameter version of forName()added in Java 2 Platform, Standard Edition (J2SE):Class.forName(String, boolean, ClassLoader).

Additionally, Class.forName()'s common form initializes the loaded class. The visible effect of this is the execution of the class's static initializers as well as byte code corresponding to initialization expressions of all static fields (this process occurs recursively for all the class's superclasses). This differs from ClassLoader.loadClass()behavior, which delays initialization until the class is used for the first time.

You can take advantage of the above behavioral differences. For example, if you are about to load a class you know has a very costly static initializer, you may choose to go ahead and load it to ensure it is found in the classpath but delay its initialization until the first time you need to make use of a field or method from this particular class.

The three-parameter method Class.forName(String, boolean, ClassLoader) is the most general of them all. You can delay initialization by setting the second parameter to false and pick a given classloader using the third parameter. I recommend always using this method for maximum flexibility.

Class initialization errors are tricky

Just because you successfully load a class does not mean there won't be any more problems. Recollect that static initialization code can throw an exception, and it will get wrapped in an instance ofjava.lang.ExceptionInInitializerError, at which point, the class becomes unusable. Thus, if it is important to process all such errors at a known point in code, you should use a Class.forName() version that performs initialization.

Furthermore, if you handle ExceptionInInitializerError and take measures so that the initialization can be retried, it will likely not work.