示例
public class ClassForNameClassLoaderTest {
public static String nihao = "nihao";
static{
System.out.println ("我是静态代码块");
}
{
System.out.println ("我是非静态代码块");
}
}
public class ClassLoaderTest {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
//执行静态代码块和静态变量的赋值
Class<ClassForNameClassLoaderTest> aClass = ( Class<ClassForNameClassLoaderTest> ) Class.forName ("builder.link.ClassForNameClassLoaderTest");
//不执行静态代码块,静态变量不会赋值
// Class<?> aClass = ClassLoader.getSystemClassLoader ().loadClass ("builder.link.ClassForNameClassLoaderTest");
//执行代码块,如果是classloader执行静态代码块 非静态代码块 静态变量赋值
aClass.newInstance ();
}
}
1.clssLoader和classForName都是用来加载类的,但是这两个方法一般却又在不同的场景使用。
如classLoader一般是spring容器用来加载bean的时候使用的,而classForName一般我们都是在使用数据库驱动的时候会使用该方法。
2.了解了两个加载类的不同场景之外后,先看一下类加载的过程。

2.1 .class文件首先被加载到jvm中
2.2然后经过链接,在链接中有3个步骤。
首先验证:验证是为了保证我们的.class文件的合法性。会分别尽心文件格式验证,元数据验证,字节码验证,符号引用验证
然后准备:初始化静态成员变量,并赋值
最后解析:将符号引用转换为直接引用
2.3初始化,执行静态代码快。类装载过程到此结束
两个方法的底层实现
Class.forName方法
public static Class<?> forName(String className)
throws ClassNotFoundException {
return forName0(className, true, ClassLoader.getCallerClassLoader());
}
接着看forName0这个方法
/** Called after security checks have been made. */
private static native Class forName0(String name, boolean initialize,ClassLoader loader)
throws ClassNotFoundException;
这里第二个参数initaline表示是否对加载的类进行初始化。
而我们的classforname传入的是true。所以classforname会对类进行初始化操作.
classloader
public Class<?> loadClass(String name) throws ClassNotFoundException {
return loadClass(name, false);
}
继续进入loadClass中,执行loadClass的是传入的false,不初始化类,
*
* @param name
* The <a href="#name">binary name</a> of the class
*
* @param resolve
* If <tt>true</tt> then resolve the class true初始化类
*
* @return The resulting <tt>Class</tt> object
*
* @throws ClassNotFoundException
* If the class could not be found
*/
protected synchronized Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
// First, check if the class has already been loaded
Class c = findLoadedClass(name);
//这段就是双亲委派的代码
if (c == null) {
try {
if (parent != null) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
// ClassNotFoundException thrown if class not found
// from the non-null parent class loader
}
if (c == null) {
// If still not found, then invoke findClass in order
// to find the class.
c = findClass(name);
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
总结两者的区别
Class.forName得到的class是已经初始化完成的
Classloder.loaderClass得到的class是还没有链接的,只是把class加载到jvm中
new和newInstance区别
1.new
①new是一个关键字
②强类型,相对高效,能调用任何public构造。
2.newInstance
①newInstance是一个方法,使用Class.forName或者Classloder.loaderClass获得class,才能调用newInstance方法 (Classloder.loaderClass获取的类,只是jvm加载了该class,并没有后续的链接等一系列的操作,当执行newInstance方法,会从链接开始加载class),调用newInstance返回object和new返回的是一样的.
②弱类型,低效率,只能调用无参构造。
网友评论