Possible Duplicate:
Difference betweeen Loading a class using ClassLoader and Class.forName
AFAIK, two ways are provided in java to init a class from its name.
-
Class
-
public static Class forName(String
className) throws
ClassNotFoundException -
public static Class forName(String
name, boolean initialize, ClassLoader
loader) throws ClassNotFoundException -
ClassLoader:
public Class loadClass(String
name) throws ClassNotFoundException {
return loadClass(name, false);
}
The known thing is in forName method, we can specify the flag of initialize to be false ,this will skip some static things to be initialized for this class. But what’s else?
And how should I use them correctly?
It’s better you can show some good examples.
Thanks!
UPDATE:
After raised question,I made some simple classLoader test.
ClassLoader cls = ClassLoader.getSystemClassLoader();
Class someClass = cls.loadClass("Test");
Class someClass0= Class.forName("Test");
Class someClass1= Class.forName("Test",false,cls);
URL[] urls = new URL[] {new File("bin/").toURL()};
ClassLoader cls2 = new URLClassLoader(urls, null);
Class someClass2 = cls2.loadClass("Test");
ClassLoader cls3 = new URLClassLoader(urls, cls);
Class someClass3 = cls3.loadClass("Test");
System.out.println(someClass.equals(someClass0));
System.out.println(someClass.equals(someClass1));
System.out.println(someClass.equals(someClass2));
System.out.println(someClass.equals(someClass3));
The result is
true,true,false,true
UPDATE
Here is my answer about
Difference between loadClass(String name) and loadClass(String name, boolean resolve)
Consider this code
The most basic API is
ClassLoader.loadClass(String name, boolean resolve)If
resolveis true, it will also try to load all classes referenced byX. In this case,Ywill also be loaded. Ifresolveis false,Ywill not be loaded at this point.There doesn’t seems to be any good reason for
resolve=true. If nobody callsX.bar(),Ywill never be needed, why should we load it at this point? And ifYis missing or corrupt, we’ll get an error trying to loadX, which is totally unnecessary.Interestingly, this method is
protected, so it’s not easy to invoke it.Another method
loadClass(name)simply callsloadClass(name,false). It’s public, and it takes the sensible choice ofresolve=false. So it is exactly what’s needed by developers.ClassLoaderonly loads classes, it does not initialize classes. We can inspect the class metadata, e.g. its super class, its annotations, its methods and fields, etc. without triggering the static initialization execution. This fact is very important for frameworks.Now,
Class.forNameBasically,
Class.forName(String name, boolean initialize, ClassLoader loader)callsloader.loadClass(name). And ifinitialize=true, the class is initialized – in theXexample, we’ll see"init class X..."printed.Class.forName(name)is the same asforName(name, true, currentLoader).Now, why would anyone want to initialize the class at this point? Wouldn’t it be better if the class is initialized only when necessary? A famous use case is JDBC initializing:
The convention is, a JDBC driver class registers itself in its static initializer. The above code will trigger the static initialization, making the driver available for subsequent uses.
From today’s point of view, that design is really odd. We usually don’t rely on static initializers. So there isn’t much justification for
initialize=true, andClass.forName(name)should be avoided.A “class literal” will return the class, without initializing it
Now, what the heck is the “currentLoader”? It is the class loader of the current class
When
X.bar()is invoked for the first time, a “Y” class is needed. what’s happening is roughly