ClassLoader.loadClass()
public class test {
public static void main(String[] args) {
Class loader = loader();
System.out.println("loader = " + loader);
}
public static Class loader(){
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
try {
Class<?> aClass = classLoader.loadClass("com.lwl.test.Factory");
return aClass;
}catch (Exception e){
throw new RuntimeException(e);
}
}
}
class Factory {
private final static Factory instance = new Factory();
private Factory() {
System.out.println("初始化");
}
public static Factory getInstance() {
return instance;
}
}
根据图的推论,我们可以得知,一个类的类加载全过程 比如会为静态变量默认值->初始值。在代码中,我使用了单例模式,也就是说,类加载时,若要为静态变量instance赋初始值的话,必然会执行构造器方法,同时执行打印,但实际运行发现,并没有执行,也就是说,这个单例甚至都没有初始化。
Class.forName()
public class test {
public static void main(String[] args) {
Class aClass = forName();
}
public static Class forName(){
try {
Class<?> aClass = Class.forName("com.lwl.test.Factory");
return aClass;
}catch (Exception e){
throw new RuntimeException(e);
}
}
}
class Factory {
private final static Factory instance = new Factory();
private Factory() {
System.out.println("初始化");
}
public static Factory getInstance() {
return instance;
}
}
当我使用Class.forName执行时,打印后发现Factory成功初始化。而这两个不同的类加载方法返回的Class对象为同一个。
造成这样的原因:
ClassLoader.loadClass的源码:
public Class<?> loadClass(String name) throws ClassNotFoundException {
return loadClass(name, false);
}
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
......
可以发现 loadClass(String name, boolean resolve)在loadClass(String name)的调用中 resolve表示是否解析Class,默认为false,而且这个方法是protected 受保护的,也就是说我们无法在外部进行调用。 loadClass(String name) 方法无法执行到initializing初始化的阶段,因为Linking阶段都没到,在loading阶段获得Class对象后,参数为false,拒绝解析Class对象,直接返回。 Class.forName的源码:
public static Class<?> forName(String className)
throws ClassNotFoundException {
Class<?> caller = Reflection.getCallerClass();
return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
}
private static native Class<?> forName0(String name, boolean initialize,
ClassLoader loader,
Class<?> caller)
throws ClassNotFoundException;
forName(String className)方法中表示是否进行initialize初始化阶段的判断参数默认值为true,且因为forName0是个private方法,无法外部调用,所以我们使用Class.forName进行类加载时,静态变量也得到了初始化赋值。一切皆由源码决定的。
总结:
Class.forName() 对于类加载的三个阶段执行完了 ClassLoader.loadClass()只执行了类加载的第一个阶段loading 获得Class对象后就返回了。 两者只有一个不同点就是,执行阶段不同!Class对象是唯一的。
|